好的,我们有这个代码:
#include <iostream>
using namespace std;
class A{
public:
A(double b, int g) {
cout << "b = " << b << ", g = " << g << endl;
}
};
int main()
{
A a = {.g = 5.0, .j = 10}; // output: b = 5, g = 10
A b = {.b = 5.0, .g = 10}; // output: b = 5, g = 10
A bb = { 4.0, 20 }; // output: b = 4, g = 20
A c = {.g = 5.0, .b = 10, 9}; // error: could not convert ‘{5.0e+0, 10, 9}’ from ‘<brace-enclosed initializer list>’ to ‘A’
A d = {.g = 5, .b = 10.0}; // error: narrowing conversion of ‘1.0e+1’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
A e = {.b = 10.0}; // error: could not convert ‘{1.0e+1}’ from ‘<brace-enclosed initializer list>’ to ‘A’
return 0;
}
main((编译的前三行,其他行在注释中产生错误。因此,实验表明:
.name =
指定的初始值设定项无效。编译器只是忽略任何命名字段- 只有{}大括号中的值的顺序才重要
- 编译器生成
<brace-enclosed initializer list>
,并查找类A的构造函数,该构造函数的参数按类型和计数与列表中的元素匹配,否则将产生错误
g++编译器9.3被使用。传递pedantic标志为{}大括号中的每个带指示符的值抛出警告
warning: C++ designated initializers only available with ‘-std=c++2a’ or ‘-std=gnu++2a’
传递-std=c++2a将隐藏警告,并为A c = {.g = 5.0, .b = 10, 9};
:提供另一条错误消息
error: either all initializer clauses should be designated or none of them should be
clang无法编译前两行,即使-std=c++2a也无法为每个生成
error: no matching constructor for initialization of 'A'
note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'double' for 1st argument
note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
Cppreference about C++中的指定初始化器只显示类字段的命名初始化的情况,而不显示构造函数参数。聚合初始化和列表初始化示例也没有显示构造函数的此类功能。
好吧,正如警告中所述,这种情况可能被视为C++20功能,但看看C++20功能以及cppreference.com中提出的功能,只会为聚合类型指定初始化,而不会像我的情况那样通过构造函数参数进行初始化。
问题:
- 为什么以及如何工作
- 它是ISO C++20还是GNU C++特性
- 应声明1。是否被视为gcc编译器静默错误
具有用户定义构造函数的类不是聚合类。如果使用指定的初始化程序,则该类应为聚合。您的程序在非聚合上使用指定的初始化程序,因此它是一个格式错误的程序。允许编译器不对其进行编译,并要求其诊断问题。
此外,指定的首字母缩写应命名集合的一个成员。您的程序没有在初始化程序中命名成员,因此格式不正确。
是ISO C++20还是GNU C++功能?
指定的初始化程序通常是标准的C++20功能,也是C++20之前的GNU功能。
使用指定的初始化程序初始化非聚合不是标准的C++功能。无论是一个bug还是一个特性,都是特定于实现的。
应状态为1。是否被视为gcc编译器静默错误?
缺少诊断消息违反了标准。
这似乎已经在主干中得到了修复,所有使用指定初始化程序的情况都是GCC中的错误:https://godbolt.org/z/TWKob6最新发布的10.2版本仍然再现了没有错误的情况。