Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In class initialization and initializer list

I have recently discovered that you cant have at the same time in class initialization and initializer list. The following code fails :

struct s
{
    int i=0;    
};
int main() {
    s s1; //s1.i = 0
    //s s2={42}; //fails
    return 0;
}

If I remove the in class initialization, the initializer list works fine !

Can someone explains me why a such thing is no allowed ?

like image 652
Davidbrcz Avatar asked Dec 20 '22 22:12

Davidbrcz


2 Answers

In fact this is allowed in C++14.

struct s
{
    int i=0;    
};

int main() {
    s s1;
    s s2 = {42}; // succeeds
}

It's likely that your compiler just isn't implementing the new rule in C++14. The latest version of clang, however, accepts this and does the correct thing in C++14 mode.

When in-class initialization was added to C++11 it was specified such that it prevented a class from being an aggregate. This was done because at the time the aggregate concept was closely related to PoD types which need to be trivially constructible. Having an in-class initialization means that a type is no longer trivially constructible. Since then, however, the two concepts have become more independent, and so for C++14 a short proposal reversing that decision was accepted.

like image 80
bames53 Avatar answered Jan 09 '23 13:01

bames53


This initialization:

s s1 = { 42 };

requires that s be an aggregate, or that it have a valid constructor taking e.g an int or an std::initializer_list.

When you add a member initialization at the point of declaration, you render your class s a non-aggregate, so you can no longer use aggregate initialization.

You could use the same initialization syntax for your non-aggregate by adding a constructor:

struct s
{
    s(int i) : i(i) {}
    int i=0;    
};

I believe this restriction has been relaxed for C++14.

See What are aggregates... for more information.

like image 35
juanchopanza Avatar answered Jan 09 '23 12:01

juanchopanza