Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ initializer list and default values

Tags:

c++

g++

c++14

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
like image 605
José Avatar asked Oct 23 '15 08:10

José


2 Answers

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.

like image 158
SingerOfTheFall Avatar answered Oct 22 '22 13:10

SingerOfTheFall


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.

like image 35
Victor Polevoy Avatar answered Oct 22 '22 11:10

Victor Polevoy