来自未选择列表初始化的数组引用的构造函数
Constructor from a reference to array not selected for list initialisation
给定以下结构:
struct A {
template<typename T, std::size_t N>
A(T const(&array)[N]) {}
template<typename T, std::size_t N>
A& operator=(T const(&array)[N]) { return *this; }
};
代码:
// a is of type A
a = {1, 2, 3, 4};
编译得很好,因为 std::initialiser_list
被隐式转换为数组引用。
然而,
A a {1, 2, 3, 4};
A a = {1, 2, 3, 4};
无法同时使用 Clang 和 GCC 进行编译。当我添加一个接受 std::initialiser_list<T>
的构造函数时,它会编译。
我错过了什么?
您只需要额外的大括号或括号:
A a{{1, 2, 3, 4}}; // ok
A b({1, 2, 3, 4}); // ok
原因是外层 braces/parens 用于 A
,内层大括号用于列表初始化的 array
对象。
通过赋值,您不需要额外的圆括号或大括号,因为函数调用隐含了它们:
a = {1, 2, 3, 4};
相当于:
a.operator=({1, 2, 3, 4});
或多或少。
It does compile when I add a constructor that accepts a std::initialiser_list<T>
.
详细说明列表初始化的工作原理。当您编写 A a{1, 2, 3, 4}
时,我们正在 首先 寻找一些 std::initializer_list<T>
构造函数(我们还没有,所以没有找到)和然后寻找一个我们可以用四个参数调用的构造函数(不存在)。添加额外的 ()
s 或 {}
s 意味着我们正在寻找一个可以使用 one 参数调用的构造函数,我们使用 1, 2 ,3, 4
对其进行初始化.
添加 std::initializer_list<T>
构造函数后,现在它就是第一阶段初始化的可行候选对象。
注意这个:
compiles just fine, since std::initialiser_list
is implicitly converted to an array reference.
不对。这个问题的任何地方都没有 std::initializer_list
。 {1, 2, 3, 4}
在 C++ 中是一件有趣的事情。它没有类型或任何东西。它只是一个 braced-init-list。它仅基于我们赋予它意义的上下文。在这种情况下,它不是转换为不同事物的事物……它只是数组初始化器的集合。
给定以下结构:
struct A {
template<typename T, std::size_t N>
A(T const(&array)[N]) {}
template<typename T, std::size_t N>
A& operator=(T const(&array)[N]) { return *this; }
};
代码:
// a is of type A
a = {1, 2, 3, 4};
编译得很好,因为 std::initialiser_list
被隐式转换为数组引用。
然而,
A a {1, 2, 3, 4};
A a = {1, 2, 3, 4};
无法同时使用 Clang 和 GCC 进行编译。当我添加一个接受 std::initialiser_list<T>
的构造函数时,它会编译。
我错过了什么?
您只需要额外的大括号或括号:
A a{{1, 2, 3, 4}}; // ok
A b({1, 2, 3, 4}); // ok
原因是外层 braces/parens 用于 A
,内层大括号用于列表初始化的 array
对象。
通过赋值,您不需要额外的圆括号或大括号,因为函数调用隐含了它们:
a = {1, 2, 3, 4};
相当于:
a.operator=({1, 2, 3, 4});
或多或少。
It does compile when I add a constructor that accepts a
std::initialiser_list<T>
.
详细说明列表初始化的工作原理。当您编写 A a{1, 2, 3, 4}
时,我们正在 首先 寻找一些 std::initializer_list<T>
构造函数(我们还没有,所以没有找到)和然后寻找一个我们可以用四个参数调用的构造函数(不存在)。添加额外的 ()
s 或 {}
s 意味着我们正在寻找一个可以使用 one 参数调用的构造函数,我们使用 1, 2 ,3, 4
对其进行初始化.
添加 std::initializer_list<T>
构造函数后,现在它就是第一阶段初始化的可行候选对象。
注意这个:
compiles just fine, since
std::initialiser_list
is implicitly converted to an array reference.
不对。这个问题的任何地方都没有 std::initializer_list
。 {1, 2, 3, 4}
在 C++ 中是一件有趣的事情。它没有类型或任何东西。它只是一个 braced-init-list。它仅基于我们赋予它意义的上下文。在这种情况下,它不是转换为不同事物的事物……它只是数组初始化器的集合。