Con*_*ery 8 c++ initializer-list aggregate-initialization
我希望有人可以给我一些技术细节,说明为什么以下内容无法编译,如果可能的话,还有一个解决方法.
我有一个名为Foo的现有结构,以及使用初始化列表创建Foo实例的代码.此代码编译和工作:
struct Foo {
int id1;
int id2;
};
int main()
{
Foo f({1,2});
return f.id1;
}
Run Code Online (Sandbox Code Playgroud)
我希望Foo能够实现一个接口:
struct Interface {
// All pure virtual methods, but this won't compile even if empty
};
struct Foo : public Interface{
int id1;
int id2;
};
int main()
{
Foo f({1,2});
return f.id1;
}
Run Code Online (Sandbox Code Playgroud)
此代码不再编译,并且存在错误
cannot convert argument 1 from 'initializer list' to 'const _Ty &'
Run Code Online (Sandbox Code Playgroud)
(错误会根据您的确切编译器而改变.)
我发现有关聚合初始化的标准的这一部分:
[dcl.init.aggr]/1聚合是一个数组或类(第12条),1.1没有用户提供的,显式的或继承的构造函数(15.1),1.2没有私有或受保护的非静态数据成员(第14条) ),1.3没有虚函数(13.3),1.4没有虚拟,私有或受保护的基类(13.1).
虽然我不确定聚合初始化是否发生在这里.有人可以解释正在发生的错误,如果可能的话,可以提供我可以对界面进行的更改吗?我有几个需要这个接口的现有结构,以及许多使用这种形式的初始化的现有代码,我想尽可能少地重写它.谢谢!
您需要初始化基类,即使它是空的:
Foo f({{},1,2});
Run Code Online (Sandbox Code Playgroud)
在你所指的部分的标准中,我们可以在[dcl.init.aggr] p4.2中看到这个例子:
Run Code Online (Sandbox Code Playgroud)struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1{{1, 2}, {}, 4}; derived d2{{}, {}, 4};初始化d1.b1为1,d1.b2为2,d1.b3为42,d1.d为4,d2.b1为0,d2.b2为42,d2.b3为42,d2.d为4. - 末端的例子]
另见[dcl.init.aggr] p2,它解释了聚合的元素是什么:
聚合的元素是:
- 对于数组,数组元素按增加的下标顺序,或者
- 对于类,按声明顺序的直接基类,后跟直接非静态数据成员([class.mem]),这些成员不是匿名成员工会,按照申报顺序.
当聚合由[dcl.init.list]中指定的初始化列表初始化时,初始化列表的元素将被视为聚合元素的初始化器....
注意,答案假设C++ 17或更高版本,因为在C++ 17之前,不允许聚合具有基类.