Home > database >  Why does static_assert on a 'reference to const int' fail?
Why does static_assert on a 'reference to const int' fail?

Time:09-20

I'm now learning how to use static_assert. What I learned so far is that the argument of the static_assert has to be constant expression. For the following code, I don't know why the argument reference is not a constant expression: It is declared as const and initialized by integral constant 0:

int main()
{
    const int &reference = 0;
    static_assert(reference);
} 

The error message from gcc states that the reference is not usable in a constant expression:

error: 'reference' is not usable in a constant expression.

Is there a standard rule that prohibits reference from being usable in constant expressions so that it is not a constant expression?

CodePudding user response:

First of all, because you use static_assert(reference); instead of static_assert(!reference); the program is ill-formed whether or not the operand of static_assert is a constant expression, as the assertion will fail. The standard only requires some diagnostic for an ill-formed program. It doesn't need to describe the cause correctly. So for the following I will assume you meant static_assert(!reference);.

The initialization of reference is not a constant expression because the glvalue to which it would be initialized refers to an object which does not have static storage duration (it is a temporary bound to a reference with automatic storage duration), in violation of [expr.const]/11. (At least it seems to be the intention that a temporary lifetime-extended through a reference has the storage duration of the reference. This is not clearly specified though, see e.g. https://github.com/cplusplus/draft/issues/4840 and linked CWG issues.)

Therefore the reference is not constant-initialized (by [expr.cons]/2.2) and it is also not constexpr, so that the reference is not usable in constant expressions (by [expr.const]/4), which is however required of a reference which is referred to by an id-expression in a constant expression if its lifetime didn't start during the constant expression's evaluation (by [expr.const]/5.12). Declaring the reference constexpr only shifts the issue to the declaration failing for the same reason as above.

If you move the declaration of reference to namespace scope it will work (at least after resolution of CWG 2126 and CWG 2481).

  • Related