c++ - 为什么 constexpr 函数对于引用的行为有所不同?

标签 c++ constexpr

灵感来自Counting function arguments at compile time

考虑this code :

template <typename... Args>
constexpr int count(Args&&...)
{
    return sizeof...(Args);
}

void foo(int value)
{
    static_assert(count(value) >= 0);  // OK

    const int& ref = 7;
    static_assert(count(ref) >= 0);  // Error
}

第一个static_assert工作正常。第二个给出错误:

<source>:12:19: error: static_assert expression is not an integral constant expression
    static_assert(count(ref) >= 0);
                  ^~~~~~~~~~~~~~~
<source>:12:25: note: initializer of 'ref' is not a constant expression
    static_assert(count(ref) >= 0);
                        ^
<source>:11:16: note: declared here
    const int& ref = 7;
               ^

这两种情况都让我感到惊讶。为什么第一个 static_assert 工作正常,而 value 在编译时显然未知?为什么第二个 static_assert 不起作用,而与第一个的唯一根本区别是它提供的是引用,而不是值?

最佳答案

与常量表达式一样,我们需要查阅[expr.const]中的列表,看看我们编写的任何子表达式是否是不允许的。在这种情况下,相关的项目符号是:

2.11 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 initialized with a constant expression or
  • its lifetime began within the evaluation of e;

这就是将ref从水中敲出来的原因。它不会随着 count(ref) 的计算而存在,因为它是预先声明的,并且它不是用常量表达式初始化的。这可能是 7,但实际的初始化程序是一个临时对象,因为那是引用绑定(bind)的对象。

至于value是否可用。这是因为没有项目符号不允许 value 本身。现在,引用参数的生命周期从 count(value) 的计算开始,而不是提前。因此,它是在常量表达式中创建的有效引用,但它不能用于读取

关于c++ - 为什么 constexpr 函数对于引用的行为有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58472449/

相关文章:

c++ - 使用 operator[] 和 operator int() 的模糊重载

c++ - 分配指向固定大小数组的指针

c++ - 非模板类与模板类的多重定义

c++ - 为什么 constexpr 与模板一起工作?

c++ - std::initializer_list 和 c array [] 的优缺点是什么?

c++ - 为什么 std::function 没有进行类型检查?

C++ 模板 : Calling member function of derived template class from base class

c++ - g++-7.0/访问硬件中 constexpr 函数的不同行为

c++ - 可以制作一个constexpr树吗?

c++ - 为什么我的 constexpr 函数不能返回 lambda?