5

我正在尝试初始化事物类型的对象:

template<typename T>
  struct thing : std::array<std::array<T, 2>, 2>
  {
  };

thing<int> t1 {{ {1,2}, {3,4} }};

我得到:

 error: no matching function for call to ‘thing<int>::thing(<brace-enclosed initializer list>)’
 thing<int> t1 {{{1,2},{3,4}}};

同上

thing<int> t0{{ 1, 2, 3, 4 }};

和其他几件事。

4

1 回答 1

9

如果您使用的是 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}} }} };

如果您尝试做的是thingan 的别名array<array<T,2>,2>,那么您不需要上述任何一个。利用

template<typename T>
using thing = std::array<std::array<T, 2>, 2>;

thing<int> t{{ {{1,2}}, {{3,4}} }};
于 2014-07-25T15:07:07.590 回答