【问题标题】:Designated initializers in C++20C++20 中的指定初始化器
【发布时间】:2020-03-11 13:08:30
【问题描述】:

我有一个关于 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++ aggregate c++20 designated-initializer


【解决方案1】:

根据 C++ 20 标准(9.3.1 聚合。第 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 由非指定的初始化器列表初始化。

【讨论】:

  • 或混合:Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };.
  • @Jarod42 是的,它可以编译。
  • 不,它不编译。
【解决方案2】:

您可能有多个来自不同基础的同名字段,

从逻辑上讲,您应该提供所需基地的名称,但似乎没有办法做到这一点。

// 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++中是不允许的。

【讨论】:

  • .age{40} 会产生braces around scalar initializer 警告,对吧?你知道为什么会发生这种情况以及如何避免吗?
猜你喜欢
  • 2019-04-14
  • 2021-03-25
  • 2020-07-20
  • 2020-01-13
  • 2023-04-09
  • 1970-01-01
  • 2020-01-13
  • 2010-10-25
相关资源
最近更新 更多