11

I have a struct that I'd like to initialize using an initializer list

struct Parent{};

struct Child : private Parent {
    int b;
};

int main() {
    Child c{ 1 };
    return 0;
}

Looking at other questions I found this answer that states that it should be possible in c++17.

However when I try the above snippet in VS2017 I get

Error   C2440   'initializing': cannot convert from 'initializer list' to 'child'

Is there any way to utilize this new feature?

Bomaz
  • 1,871
  • 1
  • 17
  • 22
  • 3
    With little modification, it works with gcc: [Demo](http://coliru.stacked-crooked.com/a/d89101d38847de7a). Remove `private` and initialize base `Parent`. – Jarod42 Nov 16 '17 at 15:54

2 Answers2

17

With inheritance, each base class subobject of the aggregate is initialized like a member. So to aggregate initialization, Child has two subobjects: Parent, and i. So you need two initializers in your braced-init-list:

Child c{ {}, 1 };

Also, in order for Child to be an aggregate, all subobjects must be public. So you can't have private base classes.

Of course, this assumes that Visual Studio implements the feature correctly. VS2017 15.5 is not C++17 compliant, but 15.7 supports this.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • apparently it doesn't implement it. At least not yet. https://blogs.msdn.microsoft.com/vcblog/2017/08/11/c17-features-and-stl-fixes-in-vs-2017-15-3/ – Bomaz Nov 16 '17 at 16:13
  • @Bomaz I'm not seeing it in there, could you at least give me something to search for. – Jonathan Mee Nov 26 '18 at 16:24
  • 1
    @JonathanMee: It's called "Extended aggregate initialization", and it's listed (on that page) as "No". Note that VS15.7 supports this. – Nicol Bolas Nov 26 '18 at 16:35
  • 1
    Heh... Well I'd typed up an answer extending yours before I saw you commented back. Shouldaknown you're too involved to leave an incomplete answer. Thank you for improving +1. Also I'll leave my answer just cause I went to all the trouble of typing it. But I've added the source link to your answer lest anyone think I figured it out on my own :) – Jonathan Mee Nov 26 '18 at 17:13
7

has introduced an Extension to Aggregate Initialization(P0017R1) which provides for the construction of a derived instance while still explicitly initializing the base class:

struct base { int a1, a2; };
struct derived : base { int b1; };

derived d1{{1, 2}, 3};      // full explicit initialization
derived d1{{}, 1};          // the base is value initialized

Thus using the "Extension to Aggregate Initialization" you'll want to use the code: Child c{ {}, 1 } as mentioned in Nicol Bolas's answer again with his caveat that you'd need to use public not private inheritance to do aggregate initialization at all.

Unfortunately did not support P0017R1 until version 15.7. So it may be necessary to upgrade your Visual Studio to accomplish this.


If that's not possible, and you're able to get by without polymorphisim, you can temporarily define:

struct Child {
    Parent a;
    int b;
};

Which would allow you to use the consistent code: Child c{ {}, 1 } now and whenever you change back to inheritance after upgrading to 15.7.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288