Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible MSVC 2013 bug when initializing struct members

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'

like image 312
Eissa N. Avatar asked Jun 28 '16 01:06

Eissa N.


1 Answers

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 forms

T 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.

like image 150
Lightness Races in Orbit Avatar answered Sep 28 '22 10:09

Lightness Races in Orbit