Why constexpr allows a function whose result cannot be used in constexpr variable?

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. The only use case for constexpr function is its ability to be resolved at compile time. Or to be more exact the ability to initialize constexpr variable with its result. If you store result of constexpr function into constexpr variable it forces the function to be pure (looks like not sure). So the question is why function add below is allowed to be marked as constexpr:

int global=200;
constexpr int add(int a) {

    global += a; //works perfectly at run-time but no way to run at compile time
    return global;
}

int main() {

    constexpr int a = add(1);//will not run since attempts to access run-time storage, global not const and so on 
    int b = add(1);//works but at run-time only yet marked as constexpr

}

What is the use case for such function why it’s allowed at all? constexpr function can work with run time input since allowed to be used at run time. But what is the purpose to allow non const runtime variables within function body that kill whole purpose of constexpr?

Does someone knows why standard allows such functions?

>Solution :

From cppreference (emphasize mine) Before C++23,

A constexpr function must satisfy the following requirement:

  • [..]
  • there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.

So no diagnostic is required.

Clang/gcc succeed to diagnose the issue Demo.

In C++23, it is now legal to have such function

It is possible to write a constexpr function whose invocation can never satisfy the requirements of a core constant expression.

Rational can be found on the paper Relaxing some constexpr restrictions.

Roughly, it is to be future-proof (in general case):
Methods not constexpr in version N might become constexpr in version N+1.

Leave a Reply