I am really confused about a constexpr
concept, as I have read constexpr
is evaluated at compile time, so it is useful for performance optimization versus normal const
.
constexpr int i = 0;
constexpr int& ri = i;
The above code returns an error "invalid initialization of reference of type 'int&' from expression of type 'const int'", why?
Also, the next code has an error:
constexpr int i = 0;
constexpr int* ri = &i;
If I replaced the constexpr
keyword with const
, all above worked correctly.
As you said,
constexpr
is evaluated at compile time. So the value must be evaluable when compiling.For example:
For first line, 0 is evaluable when compiling, its value is 0.
But for second line, compiler needs address of
i
to do the assignment, which is determined at runtime. So this line will fail.Re
A
const int*
essentially means(const int)*
, except that you can't use parentheses that way. Aconstexpr int*
meansconstepxr (int*)
(ditto note).This is because
constexpr
is not part of the type, you can't name the typeconstexpr int
, say, whileconst
is part of the type.Instead of
which attempts to declare a
constexpr
reference to non-const
, just writeYou can read that backwards as
ri
is a reference to aconst
int
which isconstexpr
(evaluated at compile time).Addendum:
It ¹appears that C++14 requires local non-
static
constexpr
objects to have automatic storage duration, modulo the as-if rule for optimization.To cater for this, i.e. to make the code portable across compilers, if the above declarations appear locally in a function, add
static
to ensure static storage duration for the object that one refers to:Otherwise it may not compile with e.g. g++, and it's probably what the C++14 and C++11 standards require, by omission of suitable constraints on
constexpr
.Notes:
¹ See the discussion of R. Sahu's answer.
Here are my 2 cents:
The
constexpr
feature defines computation that happens during the compile time. Reasonable question:Reasonable answer:
Because of that standard allows pretty limited set of features inside the
constexpr
code. One may argue why exactly this set and not something more? Well, later on the standard may evolve and allow more.The second line is a problem because the pointer does not point to a
const
object. The pointer itself isconst
.Using
solves that problem. However, that will be still a problem if the variables are defined in a function scope.
is a valid program.
is not a valid program.
Here's what the C++11 standard has to say about address constant expression: