c++ - 表达式未评估为常量两级 constexpr 函数(编译器错误?)

标签 c++ templates c++17 constexpr compile-time-constant

我有以下代码:

#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

最佳答案

来自 [expr.const]/4 :

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 绑定(bind)到变量 a 来进入常量评估,而在另一种情况下,我们绑定(bind) a引用另一个引用。

不过,如果您按值(value)衡量,两者都应该有效。

关于c++ - 表达式未评估为常量两级 constexpr 函数(编译器错误?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56891485/

相关文章:

c++ - 有没有办法使用预处理器将文本资源拉入原始字符串文字?

c++ - std::atomic_thread_fence 具有 undefined reference

c++ - 具有多个 GUI 屏幕的程序的设计方法

c++ - 返回本地对象的元组

c++ - 将 std::bind 与 std::visit 一起使用

c++ - FFMPEG TS空包传输

c++ - 类模板成员的特化

C++:返回指向模板子类的指针

c++ - 各种类型的默认模板参数

c++ - 注入(inject)的类名作为类型