C ++ 20の指定イニシャライザ


25

c ++ 20機能の1つである指定イニシャライザについて質問があります(この機能の詳細はこちら

#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}}; 
}

このコードはgcc 9.2.0と-Wall -Wextra -std=gnu++2aフラグを使用してコンパイルされています。

上記のように、両方の構造体PersonEmployeeは集合体ですが、Employee指定された初期化子を使用して集合体を初期化することはできません。

なぜ誰かが私に理由を説明できますか?


それがあなたの問題を解決するかどうかはわかりませんが、あなたはここでパブリックを継承しないかもしれません...struct Employee : public Person
skratchi.at


@GSergわかりました。ええと... 毎回使っているのでpublicprivate毎回使っているので、私はそれについて考えを無駄にしたことはありません...とにかくありがとう
skratchi.at

あなたが得るあなたの正確なエラーは何ですか?
skratchi.at、

2
@ skratchi.at structsはデフォルトでパブリックに継承されます
idclev 463035818

回答:


15

C ++ 20標準に準拠(9.3.1集計。p。#3)

(3.1)—イニシャライザリストが指定イニシャライザリストである場合、集約はクラスタイプでなければならず、各指定子の識別子は、クラスの直接の非静的データメンバー、および集約の明示的に初期化された要素を指定するものとします。これらのメンバーである、またはそれらを含む要素です。

そのため、指定された初期化リストを使用して、基本クラスのデータメンバーを初期化することはできません。

代わりに通常のリストの初期化を代わりに使用してください

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

または

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

または@ Jarod42がコメントで指摘したように、あなたは書くことができます

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

この場合、直接基本クラスは指定されたイニシャライザリストによって初期化されますが、クラスEmploye全体は指定されていないイニシャライザリストによって初期化されます。


3
またはミックス:Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };
Jarod42

@ Jarod42はい、コンパイルします。
モスクワ出身のVlad、

5

異なるベースからの同じ名前のいくつかのフィールドがあるかもしれません、

論理的には、必要なベースの名前を指定する必要がありますが、それを行う方法はないようです。

// 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}};

さらに、C ++で指定された初期化は、Cよりも制限されています。

注:順不同の指定された初期化、ネストされた指定された初期化、指定された初期化子と通常の初期化子の混合、配列の指定された初期化はすべてCプログラミング言語でサポートされていますが、C ++では許可されていません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.