簡體   English   中英

在 c++17 中編譯的簡單代碼在 c++20 中產生錯誤

[英]simple code that compile in c++17 produce error with c++20

當我從 std=c++17 切換到 std=c++20 時,gcc/clang 返回了一個奇怪的錯誤。

struct Matrix2 {
   double ptr[9];

   // defaults
   Matrix2()                          = default; // constructor
   Matrix2(const Matrix2&)            = default; // copy constructor
   Matrix2(Matrix2&&)                 = default; // move constructor
   Matrix2& operator=(const Matrix2&) = default; // copy assignment operator
   Matrix2& operator=(Matrix2&&)      = default; // move assignment operator
   ~Matrix2()                         = default; // destructor

};

constexpr Matrix2 Id2() {
    return {   1.0   ,   0.0   ,   0.0   ,
               0.0   ,   1.0   ,   0.0   ,
               0.0   ,   0.0   ,   1.0   };
}

int main () {
   auto a = Id2();
}

使用 stdc++17,代碼編譯良好,但使用 stdc++20 會產生以下錯誤: could not convert '{1.0e+0, 0.0, 0.0, 0.0, 1.0e+0, 0.0, 0.0, 0.0, 1.0e+0}' from '<brace-enclosed initializer list>' to 'Matrix2'

https://godbolt.org/z/P4afYYn9d

標准現在是否禁止返回原始初始化器列表? 什么是解決方法?

多謝

C++17 和 C++20 之間的 C++ 標准發生了變化,用於聚合初始化。 看看聚合初始化(cppreference)

看解釋部分:

  • 自 c++11 起,直到 c++20 :沒有用戶提供的、繼承的或顯式的構造函數(允許顯式默認或刪除的構造函數)
  • 自 C++20 起:沒有用戶聲明或繼承的構造函數

您已經在類/結構中聲明了構造函數,因此從 C++20 開始,您不能進行這種初始化。 您必須使用初始化列表聲明自己的構造函數

[編輯:添加一些詳細示例]

或者刪除所有默認的構造函數。

你也可以有一個std::array的構造函數:

struct Matrix2 {
   std::array<double,9> ptr;

   // defaults
   Matrix2()                          = default; // constructor
   Matrix2(const Matrix2&)            = default; // copy constructor
   Matrix2(Matrix2&&)                 = default; // move constructor
   Matrix2& operator=(const Matrix2&) = default; // copy assignment operator
   Matrix2& operator=(Matrix2&&)      = default; // move assignment operator
   constexpr Matrix2(const std::array<double, 9> & arr)
   : ptr(arr) {}
   ~Matrix2()                         = default; // destructor    
};

constexpr Matrix2 Id2() {
    // not nice, requires extra brace.
    // not nice, potentially slower if the compiler misses
    // the opportunity to elide the copy of the array.
    return {{   1.0   ,   0.0   ,   0.0   ,
               0.0   ,   1.0   ,   0.0   ,
               0.0   ,   0.0   ,   1.0   }};
}

int main () {
   auto a = Id2();
}

或使用初始化列表:

struct Matrix2 {
   double ptr[9];

   // defaults
   Matrix2()                          = default; // constructor
   Matrix2(const Matrix2&)            = default; // copy constructor
   Matrix2(Matrix2&&)                 = default; // move constructor
   Matrix2& operator=(const Matrix2&) = default; // copy assignment operator
   Matrix2& operator=(Matrix2&&)      = default; // move assignment operator
   constexpr Matrix2(const std::initializer_list<double> & init)
   :ptr{}
   {
       // not nice, this is not as good as the validation 
       // the compiler does for aggregate initialization.
       assert(std::size(init) <= std::size(ptr));
       std::copy(std::begin(init), std::end(init), ptr);
   }
   ~Matrix2()                         = default; // destructor

};

constexpr Matrix2 Id2() {
    return {   1.0   ,   0.0   ,   0.0   ,
               0.0   ,   1.0   ,   0.0   ,
               0.0   ,   0.0   ,   1.0   };
}

int main () {
   auto a = Id2();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM