Why does a constexpr function behave differently for a reference?

我的未来我决定 提交于 2019-12-23 12:06:32

问题


Inspired by Counting function arguments at compile time

Consider 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
}

First static_assert works fine. Second gives an error:

<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;
               ^

Both situations are surprising to me. Why does the first static_assert work fine, while value is clearly not known at compile time? Why does the second static_assert not work, while the only fundamental difference with the first is that it is supplied with a reference, not a value?


回答1:


As is usual with constant expressions, we need to consult the list in [expr.const] and see if any sub-expression we wrote is disallowed. In this case the pertinent bullet is this one:

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;

That's what knocks ref out of the water. It did not come into existence with the evaluation of count(ref) since it's declared beforehand, and it's not initialized with a constant expression. That may be a 7, but the actual initializer is a temporary object, since that's what the reference binds with.

As for value being usable. That is because there is no bullet that disallows value itself. And the reference argument now has its lifetime begin with the evaluation of count(value), and not beforehand. So it's a valid reference to create in a constant expression, but it just can't be used to read value.



来源:https://stackoverflow.com/questions/58472449/why-does-a-constexpr-function-behave-differently-for-a-reference

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!