gcc v10 和 v9 之间的 constexpr 区别:错误或功能
constexpr difference between gcc v10 and v9: bug or feature
如果使用 gcc v10 编译,下面的代码会出现错误,但对于 gcc v9,代码没问题。
template<auto N>
struct A {
constexpr auto size() const {
return N;
}
};
template<typename T>
void foo1(const T& a) {
constexpr auto s = a.size(); // Why error here?
}
template<typename T>
void foo2(T a) {
constexpr auto s = a.size(); // OK
}
int main() {
A<10> x1;
foo1(x1);
foo2(x1);
A<x1.size()> x2; // OK
constexpr auto s = x1.size(); // OK
}
根据我的理解,成员函数 size() 在所有情况下都可以称为 constexpr。但是有一种情况 gcc10 的行为与 gcc9 相比发生了变化:如果参数由 const-ref 传递。
我不明白为什么这不应该是 constexpr?
另一个例子:
template<auto N>
struct A {
constexpr auto size() const {
return N;
}
};
template<typename T>
constexpr void foo1(const T& a) {
constexpr auto s = a.size(); // Why error here?
return s;
}
template<typename T>
constexpr auto foo2(const T& a) {
return a.size(); // Why OK here
}
int main() {
A<10> x1;
constexpr auto s1 = foo1(x1);
constexpr auto s2 = foo2(x1);
}
我不明白其中的区别。
这是GCC bug 66477。它提到 GCC 错误地接受常量表达式中的引用类型参数。
此错误已针对 GCC 10 修复。
常量表达式中不允许a.size()
的原因在中有提到。
如果使用 gcc v10 编译,下面的代码会出现错误,但对于 gcc v9,代码没问题。
template<auto N>
struct A {
constexpr auto size() const {
return N;
}
};
template<typename T>
void foo1(const T& a) {
constexpr auto s = a.size(); // Why error here?
}
template<typename T>
void foo2(T a) {
constexpr auto s = a.size(); // OK
}
int main() {
A<10> x1;
foo1(x1);
foo2(x1);
A<x1.size()> x2; // OK
constexpr auto s = x1.size(); // OK
}
根据我的理解,成员函数 size() 在所有情况下都可以称为 constexpr。但是有一种情况 gcc10 的行为与 gcc9 相比发生了变化:如果参数由 const-ref 传递。 我不明白为什么这不应该是 constexpr?
另一个例子:
template<auto N>
struct A {
constexpr auto size() const {
return N;
}
};
template<typename T>
constexpr void foo1(const T& a) {
constexpr auto s = a.size(); // Why error here?
return s;
}
template<typename T>
constexpr auto foo2(const T& a) {
return a.size(); // Why OK here
}
int main() {
A<10> x1;
constexpr auto s1 = foo1(x1);
constexpr auto s2 = foo2(x1);
}
我不明白其中的区别。
这是GCC bug 66477。它提到 GCC 错误地接受常量表达式中的引用类型参数。
此错误已针对 GCC 10 修复。
常量表达式中不允许a.size()
的原因在