6

Is this code valid with C++14

using namespace std;
struct Point
{
  int x = 0;
  int y = 0;
};
Point p2 {1, 1};

It compiles fine with clang++ 7.0, it doesn't work with G++ 4.9 in both cases I pass --std=c++1y to the compiler.

In G++ it works when I remove the default values from the struct definition.

g++ test_constexpr_ctor.cc --std=c++1y -o test
test_constexpr_ctor.cc:7:15: error: no matching function for call to ‘Point::Point(<brace-enclosed initializer list>)’
Point p2 {1, 1};
            ^
test_constexpr_ctor.cc:7:15: note: candidates are:
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point()
struct Point
        ^
test_constexpr_ctor.cc:1:8: note:   candidate expects 0 arguments, 2 provided
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point(const Point&)
test_constexpr_ctor.cc:1:8: note:   candidate expects 1 argument, 2 provided
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point(Point&&)
test_constexpr_ctor.cc:1:8: note:   candidate expects 1 argument, 2 provided
VP.
  • 15,509
  • 17
  • 91
  • 161
José
  • 3,041
  • 8
  • 37
  • 58
  • Most probably a gcc 4.9 bug. – 101010 Oct 23 '15 at 08:32
  • 3
    It is a bug of old g++. Update it to a newer version and it compiles succesfully. – VP. Oct 23 '15 at 08:32
  • @VictorPolevoy what G++ version did you test? – José Oct 23 '15 at 08:40
  • 1
    `g++ 5.1.0` is enough. – VP. Oct 23 '15 at 08:42
  • 1
    @101010 yes it is a bug, see [C++11 aggregate initialization for classes with non-static member initializers](http://stackoverflow.com/q/27118535/1708801) and [g++ 4.9 rejects valid aggregate initialization in C++14](http://stackoverflow.com/q/28113750/1708801) ... last looks like a duplicate – Shafik Yaghmour Oct 23 '15 at 09:22

2 Answers2

3

The code is valid.

  1. (8.5.4/3):

List-initialization of an object or reference of type T is defined as follows: — If T is an aggregate, aggregate initialization is performed

  1. An aggregate in c++14 is defined as (8.5.1/1):

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

Note that in c++11 this definition looked different (emphasis mine):

An aggregate is an array or a class (Clause 9 ) with no user-provided constructors ( 12.1 ), no brace-or-equal- initializer s 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 ).

Since this part is removed in c++14, your struct is definitely an aggregate and thus aggregate initialization should be performed.

This is fixed in gcc5 (search the changes list for "aggregates with non-static data member initializers"). I wouldn't call it a "bug" though, it's rather the gcc team only implemented that change in gcc 5.1.0.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
3

The code you posted is absolutely correct.

However the behaviour you have is a not yet closed bug of G++ version 4.9.1. Actually, it may be a duplicate and closed in some other bug report, because the problem is fixed since g++ 5.1.0 or maybe even earlier version. To find actual bug you may use bugzilla's search.

VP.
  • 15,509
  • 17
  • 91
  • 161