I have a strange error returned by gcc/clang When I switch from std=c++17 to std=c++20.
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();
}
with stdc++17, the code compile fine, but with stdc++20 this produce the following error: 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
Does the standard now prohibit returning raw initializer_list?? and what is the work around??
Thx a lot
There was a change in the C++ standard between C++17 and C++20 for aggregate initialization. Have a look at aggregate initialization (cppreference)
Look at the explanation section:
You have declared constructors in your class/struct, so as of C++20 you can't have this kind of initialization. You'd have to declare your own constructor with initialization list
[edit: adding some detailed examples]
Or remove all the defaulted constructors.
You could also have a constructor from 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();
}
Or with initialization list:
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();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.