C ++ 20中的指定初始值设定项

我对一个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"},.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聚合的初始化无法使用指定的初始化程序进行。

有人可以解释一下为什么吗?

oo748899 回答:C ++ 20中的指定初始值设定项

根据C ++ 20标准(9.3.1汇总。第3页)

  

(3.1)—如果初始化列表是一个指定的初始化列表,则   集合应为类类型,每个标识符中的标识符   应命名该类的直接非静态数据成员,并且   集合中显式初始化的元素是   是或包含这些成员。

因此,您不得使用指定的初始化程序列表来初始化基类的数据成员。

使用常规的列表初始化,例如

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

Employee e1{ { "John",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"},.age{40}},.salary{50000}};

此外,C ++指定的初始化比C:的约束更多:

  

注意:乱序的指定初始化,嵌套的指定初始化,指定的初始化程序和常规初始化程序的混合以及数组的指定初始化在C编程语言中均受支持,但在C ++中是不允许的。

本文链接:https://www.f2er.com/3095841.html

大家都在问