问题
MSVC 2013 complains about the following code, while it works as expected in g++. Does this look like a bug in 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;
}
Note that changing the struct
as follows resolves the issue.
struct A
{
double x, y;
};
The error message is:
Error 1 error C2440: 'initializing' : cannot convert from 'initializer-list' to 'A'
回答1:
Actually, Visual Studio is correct.
Your class is not an aggregate, so aggregate initialisation may not be used on it:
[C++11: 8.5.1/1]:
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).
[C++11: 8.5.1/15]:
The initialization that occurs in the formsT x(a); T x{a};
as well as in
new
expressions (5.3.4),static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.
[C++11: 8.5.1/16]:
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression. The source type is not defined when the initializer is a braced-init-list or when it is a parenthesized list of expressions.
- If the initializer is a braced-init-list, the object is list-initialized (8.5.4).
- [...]
And I shan't quote it all, but [C++11: 8.5.4/3]
, where list-initialization is defined, is where our story ends. It shows that without an initializer-list constructor, and given that your list has two elements (not one and not zero), your program is ill-formed.
GCC actually doesn't accept your program (example thanks to Igor), though clang erroneously does (example, same credit).
If you are right, these are some terrible news for simple structures because I tend to use default initialization everywhere:
struct A { double x{}, y{}; };
Yep, time to stop doing that, if you want your C++11 classes to be aggregates. :)
C++14 actually removed the brace-or-equal-initializers restriction from 8.5.1/1
, so switching to a newer standard will get you where you want to be.
来源:https://stackoverflow.com/questions/38065676/possible-msvc-2013-bug-when-initializing-struct-members