c++c++20designated-initializer

How to use designated initialization of derived aggregates in C++?


I have an aggregate structure B derived from another aggregate A. I would like to initialize it and there are two options: ordinary aggregate initialization and C++20 designated initializers:

struct A {};
struct B : A { int x; };

int main() {
    [[maybe_unused]] B x{{},1}; //ok everywhere
    [[maybe_unused]] B y{.x=1}; //warning in GCC
}

The ordinary initialization {{},1} works fine, but it looks too clumsy in this case due to extra {} for parent aggregate.

And designated initializers {.x=1} look better to me here, but they produce a weird warning in GCC:

warning: missing initializer for member 'B::<anonymous>' [-Wmissing-field-initializers]
    6 |     [[maybe_unused]] B y{.x=1}; //warning in GCC
      |                              ^

Demo: https://gcc.godbolt.org/z/8jEYY16c6

Is there a way to use designated initializers here and calm down GCC at the same time to eliminate the warning?


Solution

  • Is there a way to use designated initializers here and calm down GCC at the same time to eliminate the warning?

    No. GCC's warning is correct: you are missing an initializer for the base class, A. Now, in this case you happen to want to initialize from = {} anyway (which is what happens when you don't provide an initializer) and that's the only thing you can initialize it from, so maybe in this specific case it's a bit silly to warn (but in the general case where the base class actually has members, it is totally reasonable). Also the warning could be more useful and actually tell you which member you're missing an initializer for...

    Unfortunately, there is no way to actually name the base class in a designated-initializer-list, which means there's no way to actually initialize B using designated initializers.

    There is a proposal to fix this (P2287), the intent of which would be to allow B{.A={}, .x=1}, but that's still a work in progress.