Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutating an int inside a constexpr function

Tags:

Why can I do this:

constexpr auto i_can() {    int a = 8;    a = 9;    //... } 

But I cannot do this:

constexpr auto i_cannot() {     std::array<int, 10> arr{};     //I cannot     arr[5] = 9; } 

My questions are:

  1. If I can mutate an int, why can I not mutate an int that is inside the array?
  2. Is this a language limitation (C++14) or a standard library spec problem? reference std::array<T, N>::operator[](size_t) is not currently constexpr.
like image 474
Germán Diago Avatar asked Aug 09 '15 10:08

Germán Diago


People also ask

Can constexpr be modified?

According to the proposal, an object created within a constexpr expression, can now be changed during the evaluation process - until the evaluation process or the object's lifetime ends.

Is constexpr always const?

A constexpr variable must be initialized at compile time. All constexpr variables are const . A variable can be declared with constexpr , when it has a literal type and is initialized. If the initialization is performed by a constructor, the constructor must be declared as constexpr .

Does constexpr imply static?

constexpr int a = 2; Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Where to define constexpr?

constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.


1 Answers

Modification of objects inside constexpr functions has been introduced with C++14. However, while modifying e.g. a scalar by an assignment is fine, modifying a class object through a member function still needs that member function to be constexpr. And unfortunately, as you mentioned, the current std::array specification does not declare the non-const operator[] as constexpr.
Hence, §7.1.5/5 makes your definition ill-formed:

For a non-template, non-defaulted constexpr function […], if no argument values exist such that an invocation of the function […] could be an evaluated subexpression of a core constant expression (5.20), […], the program is ill-formed; no diagnostic required.

You can temporarily use a more modern implementation if you want full constexpr-ness. E.g. Constainer::Array.

like image 143
Columbo Avatar answered Oct 21 '22 03:10

Columbo