为什么指定的初始化被gcc接受而没有效果,并且生成的聚合以某种方式作为参数传递给类构造函数



好的,我们有这个代码:

#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((编译的前三行,其他行在注释中产生错误。因此,实验表明:

  1. .name =指定的初始值设定项无效。编译器只是忽略任何命名字段
  2. 只有{}大括号中的值的顺序才重要
  3. 编译器生成<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版本仍然再现了没有错误的情况。

相关内容

  • 没有找到相关文章

最新更新