Designated initializers in C++20
Asked Answered
J

2

41

I've got a question about one of the c++20 feature, designated initializers (more info about this feature here)

#include <iostream>

constexpr unsigned DEFAULT_SALARY {10000};

struct Person
{
    std::string name{};
    std::string surname{};
    unsigned age{};
};

struct Employee : Person
{
    unsigned salary{DEFAULT_SALARY};
};

int main()
{
    std::cout << std::boolalpha << std::is_aggregate_v<Person> << '\n'; // true is printed
    std::cout << std::boolalpha << std::is_aggregate_v<Employee> << '\n'; // true is printed

    Person p{.name{"John"}, .surname{"Wick"}, .age{40}}; // it's ok
    Employee e1{.name{"John"}, .surname{"Wick"}, .age{40}, .salary{50000}}; // doesn't compile, WHY ?

    // For e2 compiler prints a warning "missing initializer for member 'Employee::<anonymous>' [-Wmissing-field-initializers]"
    Employee e2 {.salary{55000}}; 
}

This code was compiled with gcc 9.2.0 and -Wall -Wextra -std=gnu++2a flags.

As you can see above, both structs, Person and Employee are aggregates but initialization of Employee aggregate isn't possible using designated initializers.

Could someone explain me why ?

Jacksnipe answered 15/11, 2019 at 11:22 Comment(3)
what is your exact error you get??Christmas
There is a similar question on SO. But is appears to answer, why it won't work. https://mcmap.net/q/393197/-brace-initialization-for-inherited-podChristmas
@Christmas if you want see what error I got, please use online compilere or etc. Only what you need to do is copy and paste this code (and use proper gcc version and compiler flags). Unfortunately, problem described in post "brace initialization for inherited pod" is not valid in c++17/20.Jacksnipe
S
34

According to the C++ 20 Standard (9.3.1 Aggregates. p. #3)

(3.1) — If the initializer list is a designated-initializer-list, the aggregate shall be of class type, the identifier in each designator shall name a direct non-static data member of the class, and the explicitly initialized elements of the aggregate are the elements that are, or contain, those members.

So you may not use the designated initializer list to initialize data members of base classes.

Use instead the usual list initialization like

Employee e1{ "John", "Wick", 40, 50000 };

or

Employee e1{ { "John", "Wick", 40 }, 50000 };

or as @Jarod42 pointed in a comment you can write

Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };

In this case the direct base class is initialized by a designated initializer list while the class Employe in whole is initialised by a non-designated initializer list.

Spiritualism answered 15/11, 2019 at 12:2 Comment(5)
or a mix: Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };.Orobanchaceous
@Orobanchaceous Yes, it compiles.Spiritualism
No, it does not compile.Sheliasheline
@CarloWood Yes it compilesAugustinaaugustine
The mix gives a warning: "mixture of designated and non-designated initializers in the same initializer list is a C99 extension [-Wc99-designator]"Population
O
13

You might have several fields with same name from different bases,

so logically, you should provide name of the wanted base, but it seems there is no way to do it.

// Invalid too:
Employee e1{.Person.name{"John"}, .Person.surname{"Wick"}, .Person.age{40}, .salary{50000}};
Employee e2{.Person{.name{"John"}, .surname{"Wick"}, .age{40}}, .salary{50000}};

In addition C++ designated initialization is more constrained than C:

Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++.

Orobanchaceous answered 15/11, 2019 at 11:47 Comment(2)
.age{40} will produce braces around scalar initializer warning, right? Do you know why that happens and how to avoid it?Margay
@Margay Because of -Wbraced-scalar-init (but it doesn't say why the warning even exists). Either change to .age = 40 or turn off the warning with -Wno-braced-scalar-init.Augustinaaugustine

© 2022 - 2024 — McMap. All rights reserved.