Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is constexpr a "hint" (like inline) or "a binding request" to the compiler?

Is constexpr an indicator for the compiler or does it mandate a behaviour ?

The example at hand is the following :

template<typename T> 
std::size_t constexpr getID() { return typeid(T).hash_code(); }

hash_code is a runtime constant, yet this snippet would compile even though a compile time evaluation is requested with constexpr. Only after the return value is used where a compile time constant is expected, would we get noticed that this is not usable as a constexpr function.

So is constexpr a "hint" (much like the inline keyword) or "a binding request" to the compiler ?

like image 845
Nikos Athanasiou Avatar asked May 21 '14 06:05

Nikos Athanasiou


People also ask

Is constexpr function inline?

A constexpr specifier used in a function or static data member (since C++17) declaration implies inline .

Is constexpr variable inline?

A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.

Is constexpr automatically inline?

A constexpr function or constructor is implicitly inline .

What is a constexpr?

constexpr specifies that the value of an object or a function can be evaluated at compile-time and the expression can be used in other constant expressions.


2 Answers

Is constexpr a “hint” (like inline) or “a binding request” to the compiler?

It is neither. Forget about when it is evaluated. Everything (with a few minor exceptions, notably involving volatile) is evaluated whenever the compiler deems it necessary to produce the behaviour of the C++ abstract machine. There isn't much else to say about when things are evaluated.

The compiler is free to produce code that evaluates what would be constant expressions at runtime if that doesn't produce a different behaviour. It is free to produce code that evaluates things not marked constexpr at compile-time if it has the smarts.

If not about compile-time vs runtime, what is constexpr about, then?

constexpr allows things to be treated as constant expressions. Anything marked constexpr must have the possibility of producing a constant expression in some way.

In the case of functions, they can be able to produce constant expressions with some arguments but not others. But as long as there is some set of arguments that can result in a constant expression, a function can be marked constexpr. If such a set of arguments is used in a function call, that expression is a constant expression. Does that mean it is evaluated at compile-time? See above. It's evaluated when the compiler deems appropriate. The only thing it means is that you can use it in a context requiring a constant expression.

For variables, either they are constant expressions or not. They have no arguments, so if constexpr they always have to be initialised with constant expressions.

TL;DR: constexpr is about tagging things as being usable in constant expressions, not about deciding when to evaluate them.


With that out of the way, it appears your function template is ill-formed. There is no set of arguments that could result in a constant expression. The standard doesn't require a diagnostic for this, though.

like image 97
R. Martinho Fernandes Avatar answered Sep 23 '22 18:09

R. Martinho Fernandes


From the C++11 Wiki page:

If a constexpr function or constructor is called with arguments which aren't constant expressions, the call behaves as if the function were not constexpr, and the resulting value is not a constant expression. Likewise, if the expression in the return statement of a constexpr function does not evaluate to a constant expression for a particular invocation, the result is not a constant expression.

The constexpr specifier thus expresses the possibility to evaluate something at compile time and is subject to some restrictions when used.


For your particular snippet it seems to me that the C++11 constraint:

exactly one return statement that contains only literal values, constexpr variables and functions

is not fulfilled, as hash_code is defined to be:

size_t hash_code() const;

In this case the standard draft n3242 says:

For a constexpr function, if no function argument values exist such that the function invocation substitution would produce a constant expression (5.19), the program is ill-formed; no diagnostic required.

I believe your example fits here.

like image 33
Massimiliano Avatar answered Sep 23 '22 18:09

Massimiliano