Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform and Value-initialization [duplicate]

I try to use value-initialization for members with value-initialization for constructors (I don't know if I really use the good terms...)

So... When I define:

struct A
{
  int a_;
};

I'm able to use:

A a{5};
assert(m.a_==5);   

However, if I want to use the member brace initializer AND an initialization-list constructor

struct B
{
  int b_ {1};
};

This doesn't compile (c++14: http://ideone.com/MQ1FMU):

B b{2};

Here is the error:

prog.cpp:19:7: error: no matching function for call to 'B::B(<brace-enclosed initializer list>)'
  B b{2};
       ^
prog.cpp:19:7: note: candidates are:
prog.cpp:10:8: note: constexpr B::B()
 struct B
        ^
prog.cpp:10:8: note:   candidate expects 0 arguments, 1 provided
prog.cpp:10:8: note: constexpr B::B(const B&)
prog.cpp:10:8: note:   no known conversion for argument 1 from 'int' to 'const B&'
prog.cpp:10:8: note: constexpr B::B(B&&)
prog.cpp:10:8: note:   no known conversion for argument 1 from 'int' to 'B&&'

What is the difference, concept-wise? Many thanks!

like image 971
fp12 Avatar asked Apr 01 '15 20:04

fp12


1 Answers

Under C++11 rules, B is not an aggregate type. C++11 [dcl.init.aggr]/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).

B only has a default constructor, and thus cannot be initialized from the braced-initializer-list {2}.

C++14 allows brace-or-equal-initializers for non-static data members in an aggregate. N4140 [dcl.init.aggr]/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).

With fairly straight-forward semantics: fields for which there is no initializer specified are initialized from their brace-or-equal-initializer, if any, and otherwise initialized with {} [dcl.init.aggr]/7:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer, from an empty initializer list (8.5.4).

Your program is thus valid C++14 (DEMO). Essentially, the prohibition of brace-or-equal-initializers in C++11 was a mistake that C++14 corrected.

like image 62
Casey Avatar answered Oct 11 '22 12:10

Casey