C++ 构造函数采用 std::initializer_list 大小为 1

C++ constructor taking an std::initializer_list of size one

下面的示例程序代码背后的想法是说明这样一个事实,即当只给定一个元素时,拥有一个不等同于默认复制构造函数的初始化列表构造函数可能会导致 Clang 以某种方式出现意想不到的结果。

这也表明 Clang 和 GCC 没有在复制构造函数和初始化列表构造函数之间实现相同的优先级,这实际上使得可移植代码不可能使用这种初始化列表构造函数。

// Include directive.
#include <initializer_list>

// The struct used in this case.
struct Foo
{
  // Member value.
  int val;

  // Default constructor.
  Foo() : val(0) {}

  // Initializer list constructor.
  Foo(std::initializer_list<Foo>) : val(2) {}
};


// Main function.
int main()
{
  // Default constructed Foo object.
  Foo foo_zero;

  // It is not clear to me which constructor
  // should be called by the following statement.
  Foo foo_test = { foo_zero };

  // Return exit code.
  // Clang 6.0.0 returns 0 (i.e. implicit copy constructor was called for 'foo_test').
  // GCC 8.2 returns 2 (i.e. initializer list constructor was called for 'foo_test').
  return foo_test.val;
}

我的问题如下:

  1. 我的示例程序的 return 值应该是多少(Clang 和 GCC 似乎不一致)?

  2. 有没有办法让我的示例程序的初始化列表构造函数使用适用于 Clang 和 GCC 的语法调用?

Clang 实现了 DR 1467 (brace-initializing a T from a T behaves as if you didn't use braces) but has yet to implement DR 2137(转念一想,只对聚合执行此操作)。

您的代码应该 return 2.

可能的解决方法是 Foo foo_test({ foo_zero });