表达式未评估为常量两级 constexpr 函数(编译器错误?)
Expression did not evaluate to a constant two level constexpr functions (compiler bug?)
我有以下代码:
#include <iostream>
template<int I>
class A
{
public:
inline constexpr static int size() { return I; }
};
template<typename T>
inline constexpr auto size(const T& arg) noexcept -> decltype(arg.size())
{
return arg.size();
}
template<typename T>
inline constexpr void twoLevel(const T& arg) noexcept
{
static_assert(size(arg) > 0);
}
int main()
{
A<5> a;
static_assert(size(a)>0); //this works
twoLevel(a); // this does not
return 0;
}
无法在 msvc 上编译并出现错误 expression did not evaluate to a constant
,但可用于 gcc。 gcc 是否接受某些未定义的行为?或者它是 msvc 的编译器错误?
这是一个演示:godbolt code
An expression e
is a core constant expression unless the evaluation of e
, following the rules of the abstract machine, would evaluate one of the following expressions:
- [...]
- an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
- it is usable in constant expressions or
- its lifetime began within the evaluation of
e
;
- [...]
在:
static_assert(size(arg) > 0);
我们有一个id-expression引用一个引用类型的变量,引用没有前置初始化,所以我们没有常量表达式。
我认为:
static_assert(size(a) > 0);
由于“先于初始化”而起作用 - 我们通过直接将引用 arg
绑定到变量 a
来进入常量评估,而在另一种情况下,我们将引用绑定到另一个引用.
不过,如果您按价值计算,两者都应该有效。
我有以下代码:
#include <iostream>
template<int I>
class A
{
public:
inline constexpr static int size() { return I; }
};
template<typename T>
inline constexpr auto size(const T& arg) noexcept -> decltype(arg.size())
{
return arg.size();
}
template<typename T>
inline constexpr void twoLevel(const T& arg) noexcept
{
static_assert(size(arg) > 0);
}
int main()
{
A<5> a;
static_assert(size(a)>0); //this works
twoLevel(a); // this does not
return 0;
}
无法在 msvc 上编译并出现错误 expression did not evaluate to a constant
,但可用于 gcc。 gcc 是否接受某些未定义的行为?或者它是 msvc 的编译器错误?
这是一个演示:godbolt code
An expression
e
is a core constant expression unless the evaluation ofe
, following the rules of the abstract machine, would evaluate one of the following expressions:
- [...]
- an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
- it is usable in constant expressions or
- its lifetime began within the evaluation of
e
;- [...]
在:
static_assert(size(arg) > 0);
我们有一个id-expression引用一个引用类型的变量,引用没有前置初始化,所以我们没有常量表达式。
我认为:
static_assert(size(a) > 0);
由于“先于初始化”而起作用 - 我们通过直接将引用 arg
绑定到变量 a
来进入常量评估,而在另一种情况下,我们将引用绑定到另一个引用.
不过,如果您按价值计算,两者都应该有效。