SSY
SSY

Reputation: 667

Why is it not legal to access global non constant variable in constexpr non member function

int d = 1;
constexpr void add()
{
    d++;
}

int main()
{

}

GCC 7.1 will report errors below. The error message is very clear. The problem is that I don't see any explicit explanations in constexpr to describe it's illegal.

Can someone explain which rules defined in spec this case violate?


main.cpp: In function 'constexpr void add()':

main.cpp:8:1: error: the value of 'd' is not usable in a constant expression

 }

 ^

main.cpp:4:5: note: 'int d' is not const

 int d = 1;

     ^

Upvotes: 1

Views: 410

Answers (2)

hnefatl
hnefatl

Reputation: 6037

From cppreference:

A core constant expression is any expression that does not have any one of the following in any subexpression (ignoring unevaluated expressions such as the operand of sizeof or the right operand of builtin && when the left operand evaluates to false).

...

16) modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression.

In your example, d's lifetime began before add was evaluated - so any modification of d inside add is illegal. The example on the reference is specifically for incrementing, but this holds for all modifications.

Edit: Not quoting from the standard because as far as I'm aware, you've got to buy it...

Upvotes: 2

youngmit
youngmit

Reputation: 878

The comments are good from a refer-you-to-the-standard perspective, but here hopefully a more intuitive explanation.

A constexpr function must be reducible to a constant expression at compile time. Since you are interacting with a regular, non-const int in the function, the compiler cannot determine what d++ is under all circumstances. Consider the following case:

int d;
constexpr void add() {
    d++;
}

void foo() {
    int n;
    std::cin >> n;
    d = n;
    add();
}

In this case, the value of d inside foo() is indeterminate at compile time, and therefore, the constant expression that you are hoping add() to leave you with cannot be determined. I hope that helps.

Upvotes: 0

Related Questions