Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designated initializers in C++20

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 ?

like image 888
MateuszGierczak Avatar asked Nov 15 '19 11:11

MateuszGierczak


People also ask

What is designated initializer in C?

A designated initializer, or designator, points out a particular element to be initialized. A designator list is a comma-separated list of one or more designators. A designator list followed by an equal sign constitutes a designation.

What is a designated initializer Swift?

Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.

What is Initializers list in C++?

Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.

What is aggregate type C++?

Formal definition from the C++ standard (C++03 8.5. 1 §1): An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).


2 Answers

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.

like image 143
Vlad from Moscow Avatar answered Oct 01 '22 09:10

Vlad from Moscow


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++.

like image 24
Jarod42 Avatar answered Oct 01 '22 09:10

Jarod42