在 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
标准现在是否禁止返回原始数据initializer_list??解决方法是什么??
非常感谢
C++17 和 C++20 之间的 C++ 标准在聚合初始化方面发生了变化。看看aggregate initialization (cppreference)
看解释部分:
- 自 c++11 起,直到 c++20:无 user-provided、继承或显式构造函数(允许显式默认或删除的构造函数)
- 自 C++20: 无 user-declared 或继承的构造函数
您在 class/struct 中声明了构造函数,因此从 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();
}
当我从 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
标准现在是否禁止返回原始数据initializer_list??解决方法是什么??
非常感谢
C++17 和 C++20 之间的 C++ 标准在聚合初始化方面发生了变化。看看aggregate initialization (cppreference)
看解释部分:
- 自 c++11 起,直到 c++20:无 user-provided、继承或显式构造函数(允许显式默认或删除的构造函数)
- 自 C++20: 无 user-declared 或继承的构造函数
您在 class/struct 中声明了构造函数,因此从 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();
}