c++ - 构造函数干扰成员变量指定初始化器?

标签 c++ g++ language-lawyer c++20 designated-initializer

一段时间以来,人们已经能够在 GCC 中使用“指定初始化程序”:

struct CC{
    double a_;
    double b_;
};

CC cc{.a_ = 1., .b_ = 2.}; assert(cc.a_ == 1. and cc.b_ == 2.); // ok
CC cc{.bla = 0., .bli = 0.}; // compile error

但是,当我添加构造函数时,标签将被忽略。

struct CC{
    double a_;
    double b_;
    CC(double a, double b) : a_{a}, b_{b}{}
};

CC cc{.a_ = 1., .b_ = 2.}; assert(cc.a_ == 1. and cc.b_ == 2.); // ok
CC cc{.b_ = 2., .a_ = 1.}; // compiles but labels don't matter only the order, confusing
CC cc{.bla = 2., .bli = 1.}; // compiles but labels don't matter, confusing

换句话说,带有构造函数的初始化语法使标签的行为就像注释一样!,这可能会让人非常困惑,但最重要的是,它非常奇怪。

我用 gcc 8.1 -std=c++2a 无意中发现了这一点。

这是预期的行为吗?

引用:https://en.cppreference.com/w/cpp/language/aggregate_initialization

EDIT 2022:现在编译器支持 -std=c++20 行为是正确的。所有接受 -std=c++20(10.1 及更高版本)的 GCC 版本也接受上述代码或在应该时给出错误。

https://godbolt.org/z/h3eM3T7jK

最佳答案

编译器不应忽略指定初始化程序的标签。所有这三个带有构造函数的示例都应该是病式的。

由于 C++20 指定初始化程序功能与 GCC 的 C 样式指定初始化程序之间存在冲突,您可能会出现此行为,因为 GCC 只是将它们提供给您,您正在隐式访问它们。如果 GCC 是正确的 C++20 兼容的,一旦你给类型一个构造函数,它就不再是一个聚合,因此指定的初始化器用法将是错误的。

基本上,这是编译器默认为您提供的非 C++ 标准行为导致的驱动程序错误。很有可能,如果您关闭此功能,您将在这些情况下得到正确的编译器错误。

关于c++ - 构造函数干扰成员变量指定初始化器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52282288/

相关文章:

c++ - 运行时已知大小的二维数组列表(或 vector )的声明

c++ - 带对象的循环 vector

c++ - 无法将 Boost.Any 对象传递给 C++ Lua 绑定(bind)

c - 将2个字节转换为带符号的16位整数的正确方法是什么?

c++ - C++ 语法演化是如何管理的?

c++ - QUiLoader 忽略资源文件

c++ - 使用 SSE 指令

c++ - MinGW GCC 在没有警告或错误的情况下编译错误代码

C++类实例数组初始化

c++ - operator++ 作为后缀和前缀都不适用于 clang