ems*_*msr 5 c++ initialization c++11 list-initialization
我正在尝试初始化类型的对象:
template<typename T>
struct thing : std::array<std::array<T, 2>, 2>
{
};
thing<int> t1 {{ {1,2}, {3,4} }};
Run Code Online (Sandbox Code Playgroud)
我明白了:
error: no matching function for call to ‘thing<int>::thing(<brace-enclosed initializer list>)’
thing<int> t1 {{{1,2},{3,4}}};
Run Code Online (Sandbox Code Playgroud)
同上
thing<int> t0{{ 1, 2, 3, 4 }};
Run Code Online (Sandbox Code Playgroud)
和其他几件事.
如果您正在使用C++ 17编译器,那么您只缺少一组额外的大括号.以下编译:
thing<int> t1 { { { {1,2}, {3,4} } } };
// | | | |- braces for inner array
// | | |--- braces for outer array
// | |----- braces for base sub object of thing
// |------- braces for list initialization of thing
Run Code Online (Sandbox Code Playgroud)
C++ 17 修改了聚合规则以允许基类,只要它们public是非基类virtual.
的聚集体是一个数组或与类
(1.1)没有用户提供的,explicit或遗传构造([class.ctor]),
(1.2)无私有或保护非静态数据成员([class.access]),
(1.3)没有虚函数,
(1.4)没有虚拟,私有或受保护的基类([class.mi]).
基类现在被认为是聚合的元素,并且可以使用列表初始化进行初始化.
聚合的元素是:
(2.1)表示数组,数组元素按增加的下标顺序,或
(2.2)表示类,直接基类按声明顺序,后跟直接非静态数据成员([类] .mem])不是匿名联盟的成员,按声明顺序.
C++ 14及更早版本的答案如下:
std::array是一个聚合,使用braced-init-list完成的初始化是聚合初始化.但是,thing它不是聚合,因为它有一个基类.
来自§8.5.1/ 1 [dcl.init.aggr]
的骨料是没有用户提供的构造的阵列或一个类(第9节)(12.1),无私有或保护非静态数据成员(第11),没有基类(第10节),并且没有虚拟功能(10.3 ).
因此,聚合初始化不起作用.根据您尝试执行的操作,您要么提供构造函数thing,以获取std::array<std::array<T, 2>, 2>参数,并初始化基础子对象
template<typename T>
struct thing : std::array<std::array<T, 2>, 2>
{
thing(std::array<std::array<T, 2>, 2> arr)
: std::array<std::array<T, 2>, 2>(arr)
{}
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
Run Code Online (Sandbox Code Playgroud)
或者thing包含std::array作为数据成员.现在thing仍然是一个聚合.
template<typename T>
struct thing
{
std::array<std::array<T, 2>, 2> arr;
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
Run Code Online (Sandbox Code Playgroud)
如果您尝试做的是thinga的别名array<array<T,2>,2>,那么您不需要上述任何一个.使用
template<typename T>
using thing = std::array<std::array<T, 2>, 2>;
thing<int> t{{ {{1,2}}, {{3,4}} }};
Run Code Online (Sandbox Code Playgroud)