Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-initialization of a static constexpr variable, is it well-formed?

Given the following declaration in the global namespace:

constexpr int x = x; 

Is this well-formed?

The draft C++14 standard section 3.6.2 [basic.start.init] says:

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. [...]

What seems to make the example well defined is that x is initialized with its own value during constant initialization which will be 0 due to zero initialization.

Is this really the case? clang accepts this code while gcc produces a diagnostic:

error: the value of 'x' is not usable in a constant expression constexpr int x = x;                   ^ 
like image 842
Shafik Yaghmour Avatar asked Dec 14 '15 20:12

Shafik Yaghmour


People also ask

Are constexpr variables 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.

Is constexpr implicitly const?

In C++11, constexpr member functions are implicitly const.

What is a constexpr variable?

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.

Does constexpr 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).


1 Answers

This was clarified and made ill-formed by defect report 2026: Zero-initialization and constexpr which asks:

According to 3.6.2 [basic.start.init] paragraph 2,

Variables with static storage duration (3.7.1 [basic.stc.static]) or thread storage duration (3.7.2 [basic.stc.thread]) shall be zero-initialized (8.5 [dcl.init]) before any other initialization takes place.

Does this apply to constant initialization as well? For example, should the following be well-formed, relying on the presumed zero-initialization preceding the constant initialization?

constexpr int i = i; struct s {   constexpr s() : v(v) { }   int v; }; constexpr s s1; 

The note before the proposed resolution says:

CWG agreed that constant initialization should be considered as happening instead of zero initialization in these cases, making the declarations ill-formed.

and the proposed resolution clarifies and amongst many changes, removes the following wording:

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. [...]

and adds the following wording:

If constant initialization is not performed, a variable with static storage duration (3.7.1 [basic.stc.static]) or thread storage duration (3.7.2 [basic.stc.thread]) is zero-initialized (8.5 [dcl.init]). [...]

It is a large change, it renames [basic.start.init] to [basic.start.static] and created a new section [basic.start.dynamic] and modifies [stmt.dcl]

like image 174
Shafik Yaghmour Avatar answered Oct 22 '22 11:10

Shafik Yaghmour