C++20 中的指定初始化器
Designated initializers in 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"}, .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
标志编译的。
正如您在上面看到的,Person
和 Employee
两个结构都是聚合,但是 Employee
聚合的初始化无法使用指定的初始化程序。
有人能解释一下为什么吗?
您可能有几个来自不同基地的同名字段,
照理说,你应该提供想要的基地的名称,但似乎没有办法做到这一点。
// 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:
更受限制
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++.
根据 C++ 20 标准(9.3.1 聚合。第 #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.
所以你不能使用指定的初始化列表来初始化base classes的数据成员。
改用通常的列表初始化,如
Employee e1{ "John", "Wick", 40, 50000 };
或
Employee e1{ { "John", "Wick", 40 }, 50000 };
或如 @Jarod42 指出的那样,您可以写评论
Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };
在这种情况下,直接基础 class 由指定的初始化列表初始化,而 class 全体雇员由非指定的初始化列表初始化。
我有一个关于 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
标志编译的。
正如您在上面看到的,Person
和 Employee
两个结构都是聚合,但是 Employee
聚合的初始化无法使用指定的初始化程序。
有人能解释一下为什么吗?
您可能有几个来自不同基地的同名字段,
照理说,你应该提供想要的基地的名称,但似乎没有办法做到这一点。
// 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:
更受限制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++.
根据 C++ 20 标准(9.3.1 聚合。第 #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.
所以你不能使用指定的初始化列表来初始化base classes的数据成员。
改用通常的列表初始化,如
Employee e1{ "John", "Wick", 40, 50000 };
或
Employee e1{ { "John", "Wick", 40 }, 50000 };
或如 @Jarod42 指出的那样,您可以写评论
Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };
在这种情况下,直接基础 class 由指定的初始化列表初始化,而 class 全体雇员由非指定的初始化列表初始化。