如果您使用的是 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
C++17修改了聚合规则以允许基类,只要它们是public
和非virtual
.
从§11.6.1/1 [dcl.init.aggr]
聚合是具有(
1.1) 没有用户提供explicit
或继承的构造函数 ([class.ctor])、
(1.2) 没有私有或受保护的非静态数据成员 ([class.access])、
( 1.3) 没有虚函数,和
(1.4) 没有虚拟、私有或受保护的基类 ([class.mi])。
基类现在被视为聚合的元素,并且可以使用list-initialization对其自身进行初始化。
聚合的元素是:
(2.1) 对于数组,数组元素按递增下标顺序,或
(2.2) 对于类,按声明顺序的直接基类,然后是直接非静态数据成员 ([class .mem]) 不是匿名联合的成员,按声明顺序。
C++14 及更早版本的答案如下:
std::array
是一个聚合,使用花括号初始化列表完成的初始化是聚合初始化。但是,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}} }} };
或者已经thing
包含std::array
作为数据成员。现在thing
仍然是一个聚合。
template<typename T>
struct thing
{
std::array<std::array<T, 2>, 2> arr;
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
如果您尝试做的是thing
an 的别名array<array<T,2>,2>
,那么您不需要上述任何一个。利用
template<typename T>
using thing = std::array<std::array<T, 2>, 2>;
thing<int> t{{ {{1,2}}, {{3,4}} }};