簡體   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