为什么我不能支持初始化从另一个结构派生的结构? [英] Why can I not brace initialize a struct derived from another struct?

查看:790
本文介绍了为什么我不能支持初始化从另一个结构派生的结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行此代码:

struct X {
    int a;
};

struct Y : public X {};

X x = {0};
Y Y = {0};

我得到:

error: could not convert ‘{0}’ from ‘<brace-enclosed initializer list>’ to ‘Y’

为什么大括号初始化对基类而不是派生类有效?

Why does brace initialization work for the base class but not the derived class?

推荐答案

您的问题与聚合初始化有关: struct X 是一个聚合,而 struct Y 则不是。下面是关于聚合(8.5.1)的标准引用:

Your problem has to do with aggregate initialization: struct X is an aggregate while struct Y is not. Here is the standard quote about aggregates (8.5.1):


聚合是数组或类 - 提供的构造函数(12.1),非静态数据成员(9.2),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚拟函数(10.3)。

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

此子句指定如果 class 基类,那么它不是一个聚合。这里, struct Y struct X 作为基类,因此不能是聚合类型。

This clause specifies that if a class has a base class, then it's not an aggregate. Here, struct Y has struct X as a base class and thus cannot be an aggregate type.

关于您遇到的特定问题,请遵循标准中的以下条款:

Concerning the particular problem you have, take the following clause from the standard:


由初始化器列表初始化,如8.5.4中所述,初始化器列表的元素被作为聚合成员的初始化器,以增加下标或成员顺序。每个成员都从相应的initializer子句进行复制初始化。如果initializer-clause是一个表达式,并且需要缩小转换(8.5.4)来转换表达式,那么程序就会生成错误。

When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause. If the initializer-clause is an expression and a narrowing conversion (8.5.4) is required to convert the expression, the program is ill-formed.

X x = {0} 时,使用聚合初始化来初始化 a 0 。但是,当您执行 Y y = {0} 时,由于 struct Y 不是聚合类型,寻找一个合适的构造函数。因为没有隐式生成的构造函数(默认,复制和移动)可以用单个整数做任何事情,编译器会拒绝您的代码。

When you do X x = {0}, aggregate initialization is used to initialize a to 0. However, when you do Y y = {0}, since struct Y is not an aggregate type, the compiler will look for an appropriate constructor. Since none of the implicitely generated constructors (default, copy and move) can do anything with a single integer, the compiler rejects your code.

关于此构造函数查找,来自clang ++的错误消息对于编译器实际尝试做什么有点更清楚(在线示例):

Concerning this constructors lookup, the error messages from clang++ are a little bit more explicit about what the compiler is actually trying to do (online example):

Y Y = {0};
  ^   ~~~

main.cpp:5:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Y &' for 1st argument

struct Y : public X {};
       ^

main.cpp:5:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Y &&' for 1st argument

struct Y : public X {};
       ^

main.cpp:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided






请注意,有提案扩展聚合初始化以支持您的用例使它成为C ++ 17。如果我正确读取它,它使你的例子有效的语义你期望。所以...你只需要等待一个C ++ 17兼容的编译器。


Note that there is a proposal to extend aggregate initialization to support your use case, and it made it into C++17. If I read it correctly, it makes your example valid with the semantics you expect. So... you only have to wait for a C++17-compliant compiler.

这篇关于为什么我不能支持初始化从另一个结构派生的结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆