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?
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With