Eis*_* N. 5 c++ initializer-list visual-c++ c++11
MSVC 2013抱怨以下代码,而它在g ++中按预期工作.这看起来像MSVC中的错误吗?
#include <iostream>
using namespace std;
struct A
{
double x = 0.0, y = 0.0;
};
int main()
{
A a{ 1.0, 2.0 };
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,更改struct以下内容可解决此问题.
struct A
{
double x, y;
};
Run Code Online (Sandbox Code Playgroud)
错误消息是:
错误1错误C2440:'初始化':无法从'initializer-list'转换为'A'
实际上,Visual Studio是正确的.
您的类不是聚合,因此可能不会在其上使用聚合初始化:
[C++11: 8.5.1/1]:聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),非静态数据成员(9.2)没有大括号或等于初始值,没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3).
[C++11: 8.5.1/15]:表单中发生的初始化Run Code Online (Sandbox Code Playgroud)T x(a); T x{a};在
new表达式(5.3.4)中,static_cast表达式(5.2.9),函数表示法类型转换(5.2.3)以及基本和成员初始化器(12.6.2)称为直接初始化.
[C++11: 8.5.1/16]:初始化器的语义如下.的目标类型是对象或引用的类型被初始化和源类型是初始化表达式的类型.当初始化程序是braced-init-list或它是带括号的表达式列表时,未定义源类型.
- 如果初始化程序是braced-init-list,则对象将进行列表初始化(8.5.4).
- [...]
我不会引用它,但是[C++11: 8.5.4/3],在定义列表初始化的地方,我们的故事结束了.它显示没有初始化列表构造函数,并且假定您的列表有两个元素(不是一个而不是零),那么您的程序就是格式错误.
GCC实际上不接受你的程序(例如感谢Igor),虽然clang错误地做了(例如,相同的信用).
如果你是对的,这对于简单的结构来说是一些可怕的消息,因为我倾向于在任何地方使用默认初始化:
struct A { double x{}, y{}; };
是的,是时候停止这样做,如果你想要你的C++ 11类聚合.:)
C++ 14实际上删除了括号或等于初始化器的限制8.5.1/1,因此切换到更新的标准将使您获得所需的位置.