Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the initializer of a constexpr variable at class scope allowed to reference the variable?

The following code:

struct S {
    static constexpr int rolling_sum[4]{
        0,
        rolling_sum[0] + 1,
        rolling_sum[1] + 2,
        rolling_sum[2] + 3
    };
};

is accepted by clang (tested with version 12), but rejected by gcc (tested with version 11) with the following errors:

test.cpp:4:9: error: ‘rolling_sum’ was not declared in this scope
    4 |         rolling_sum[0] + 1,
      |         ^~~~~~~~~~~
test.cpp:5:9: error: ‘rolling_sum’ was not declared in this scope
    5 |         rolling_sum[1] + 2,
      |         ^~~~~~~~~~~
test.cpp:6:9: error: ‘rolling_sum’ was not declared in this scope
    6 |         rolling_sum[2] + 3
      |         ^~~~~~~~~~~

Is this code valid C++?

My guess is that it should be valid because [basic.scope.pdecl] p1 states that the point of declaration of a variable is just before its initializer, meaning the variable should be in scope in its initializer; but I'm not sure if I'm overlooking something else that could be relevant here.

like image 958
HighCommander4 Avatar asked Aug 17 '21 05:08

HighCommander4


People also ask

What does constexpr mean in C++?

constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.

Do constexpr variables take memory?

The alternatives don't have the all of the positives of static constexpr - you're guaranteed compile time processing, type safety, and (potentially) lower usage of memory (constexpr variables don't need to take up memory, they are effectively hard coded unless if possible).

Where are constexpr variables stored?

A constexpr (or indeed, any kind of variable) need not be stored anywhere if its address is never taken. A constexpr in global or namespace ,when I address it,it should store in .

Is constexpr variable inline?

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


Video Answer


2 Answers

You aren't missing anything. This is GCC bug 99059, reported in GCC 11.

Your case applies too, since just like static inline, a constexpr variable must be initialized at the point of declaration. The same lookup related bug would affect C++14 code as well.

like image 115
StoryTeller - Unslander Monica Avatar answered Nov 02 '22 06:11

StoryTeller - Unslander Monica


As your cited [basic.scope.pdecl]/1 allows (as none of /3 and forward rejects it), your program is well-formed.

We may study a similar example for which GCC confusingly rejects parts of:

struct S {
    static constexpr int x{42};
    static constexpr int y[2]{
        S::x,        // #1 GCC: OK
        S::y[0] + 1  // #2 GCC: error: incomplete type 'S' used in nested name specifier
    };
};

with an error message at #2 that should arguably (were it not a rejects-invalid) be applied to #1.

like image 21
dfrib Avatar answered Nov 02 '22 05:11

dfrib