繁体   English   中英

c++20前后指定初始化不同行为

[英]Designated initializer different behavior before and after c++20

我遇到了这种奇怪的行为,我找不到很好的解释。

下面的代码将在 c++20 之前编译成功,并且只有在使用explicit时才会失败。

struct Square {
  int area = 10;

  Square() = default; // only if this is explicit will the compile fail
  Square(const Square& other) = delete;
  Square(Square&& other) = delete;
  Square& operator =(Square&& square) = delete;
  Square& operator =(const Square& square) = delete;
};

int main() {
  Square s = {
      .area = 10
  };
}

这本身就很奇怪,但是将编译器转换为 c++20 会使上述代码失败并显示这些错误消息

gcc

无法转换大括号括起来的初始值设定项列表

clang

'Square' 的初始化没有匹配的构造函数


问题

  • 为什么它在 c++20 之前编译成功,除非explicit 换句话说,发生了什么隐式转换来实现这一点?

  • c++20 中的哪些变化导致此代码无法编译?

为什么在c++20之前编译成功...

该程序在 C++20 之前格式不正确。

在 C++20 之前的语言中不存在指定初始化器。 由于语言扩展,它可以编译。

c++20 中的哪些变化使它不再编译?

该程序在 C++20 中的格式仍然不正确。

在 C++20 中,指定的初始化程序被引入到该语言中,看起来规则与语言扩展所做的略有不同。 相关规则是(来自最新草案):

[dcl.init.list] object 或 T 类型引用的列表初始化定义如下:

  • 如果花括号初始化列表包含指定初始化列表,则 T 应为聚合 class。 ...

  • ...

[dcl.init.aggr] 聚合是一个数组或一个 class ([class])

  • 没有用户声明或继承的构造函数([class.ctor]),

  • ...

正如NathanOliver所解释的,C++20 之前语言扩展的行为差异可能与聚合定义的变化有关

在 C++20 中,您的 class 不再是聚合。 由于它不是聚合,因此您不能使用指定的初始化程序。 此更改是P1008的结果,它删除了用户提供的默认或已删除构造函数作为聚合的资格。 为什么需要进行此更改的示例是:

struct X {
  int i{4};
  X() = default;
};

int main() {
  X x1(3); // ill-formed - no matching c’tor
  X x2{3}; // compiles!
}

其中X x2{3}不应该编译,但它确实是因为X() = default; 并不能阻止它成为一个聚合体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM