Stack Overflow Asked on February 12, 2021
As far as I know, the const
qualifier in C++ basically declares internal linkage, and sometimes it allows the variable to be used as a constant expression so that it can be placed into array bounds, switch cases, etc.
But apparently this is not always the case, and I have no clue regarding the proper usage of const
and constexpr
.
Specifically, I found that when an element of a const-qualified array is used in array bounds it is not treated as a constant expression, as seen in the following code.
const int N = 3;
int foo[N] = {1, 2, 3}; // Valid
const int bar[5] = {1, 2, 3, 4, 5};
int arr[bar[2]] = {1, 2, 3}; // Invalid because a VLA can't be initialized
Using constexpr
instead of const
in the later part solves the problem. But why is the last statement invalid? And exactly what is required for an expression to be constant?
With const declaration const int bar[5] = {1, 2, 3, 4, 5};
bar[2]
is treated as a variable rather than a constant.
With constexpr declaration constexpr int bar[5] = {1, 2, 3, 4, 5};
bar[2]
is treated as a constant as expected.
In contrary, for pure integral types both const
and constexpr
declarations are threated as constants.
It's due to language rules.
For example if you look at generated assembly code for const int bar[5] = {1, 2, 3, 4, 5};
and constexpr int bar[5] = {1, 2, 3, 4, 5};
,
one can see that they are the same. So technically, both sould work.
So this verifies that limitations come from language rules, which have some historical reasons, as stated in some other answers.
Answered by StPiere on February 12, 2021
The only time const
means the same thing as constexpr
in the declaration of a variable, is when the variable is of integral or enumeration type. In addition, the initializer of this variable declaration must be a constant expression. e.g.
const int n = 42; // same as constexpr
// type is int
// initializer is integer literal, which is constant expression
std::cin >> x; // some user input
const int n = x; // NOT constexpr
// because initializer is not a constant expression
const double n = 4.2; // NOT constexpr
// type is not integral or enumeration type
Your last line of code fails to compile because bar
is not an integral or enumeration type, and hence it's not a constexpr
. Since it's not constexpr
none of its elements are constexpr
either, and hence they cannot be used as an array bound.
The reason for this special case with integers is historical: array bounds need to be constant expressions, but before C++11, the only way to express that was with a const int
. Technically, the rules could be changed to require the declaration to have constexpr
but that would break exisiting code and so it won't be changed.
And exactly what is required for an expression to be constant?
This is interesting, because the language doesn't actually say what is required for an expression to be a constant expression. Instead, it assumes that all expressions are constant expressions, and provides a list of conditions that if not satisfied will make the expression not a constant expression.
The rule is here:
An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following: ...
and this is followed by a list of conditions that make an expression not a constant expression.
Answered by cigien on February 12, 2021
It's perfectly in align with the standards
Using constexpr instead of const in the later part solves the problem.
Because constexpr evaluates the value at compile time
But why is the last statement invalid?
const int bar[5] = {1, 2, 3, 4, 5};
says that the values in bar are const values evaluated at run time
int arr[bar[2]] = {1, 2, 3};
here you are making this check at compile time . so const is throwing error. Using constexpr solves it as it deduces it at the compile time.
And exactly what is required for an expression to be constant?
declaring const to an expression tells the compiler to treat that value as const and to not allow the programmer to modify it . both const and constexpr serves the purpose but declaring makes compiler to defer initialization until run time . As compiler is checking for const value in int arr[bar[2]] at compile time it's throwing an error.
Answered by Mouse on February 12, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP