Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does the 'const' qualifier guarantee the variable to be a constant expression?

Tags:

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?

like image 380
morimn Avatar asked Jan 04 '21 07:01

morimn


People also ask

What is a const qualifier?

We use the const qualifier to declare a variable as constant. That means that we cannot change the value once the variable has been initialized. Using const has a very big benefit. For example, if you have a constant value of the value of PI, you wouldn't like any part of the program to modify that value.

What is the use of const qualifier?

The const keyword can be used as a qualifier when declaring objects, types, or member functions. When qualifying an object, using const means that the object cannot be the target of an assignment, and you cannot call any of its non-const member functions.

What is a const variable in C?

The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.

What is a const expression?

A constant expression is an expression that contains only constants. A constant expression can be evaluated during compilation rather than at run time, and can be used in any place that a constant can occur.


1 Answers

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.

like image 113
cigien Avatar answered Nov 07 '22 01:11

cigien