C ++ 20의 지정된 이니셜 라이저 surname{};

지정된 초기화 프로그램 인 C ++ 20 기능 중 하나에 대한 질문이 있습니다 (이 기능에 대한 자세한 정보는 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}};
}

이 코드는 gcc 9.2.0 및 -Wall -Wextra -std=gnu++2a플래그 로 컴파일되었습니다 .

위에서 볼 수 있듯이 두 구조체 PersonEmployee집계는 모두 있지만 Employee지정된 초기화 프로그램을 사용하여 집계를 초기화 할 수는 없습니다.

누군가 왜 나에게 설명 할 수 있습니까?



답변

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는 지정되지 않은 이니셜 라이저 목록으로 초기화됩니다.


답변

다른 기지에서 같은 이름을 가진 여러 필드가있을 수 있습니다.

따라서 논리적으로 원하는베이스의 이름을 제공해야하지만이를 수행 할 방법이없는 것 같습니다.

// 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 ++에서는 허용되지 않습니다.


답변