2015-12-14 12 views
26

die folgende Erklärung im globalen Namespace Gegeben:Selbstinitialisierung einer statischen constexpr-Variablen, ist sie wohlgeformt?

constexpr int x = x; 

Ist das gut ausgebildet?

Der Entwurf der C++ 14 Standard-Teil 3.6.2[basic.start.init] sagt:

Variables mit statischer Speicherdauer (3.7.1) oder Fadenspeicherdauer (3.7.2) erhält vor der Initialisierung initialisiert werden (8.5) . [...]

Was das Beispiel zu machen scheint gut definiert ist, dass x mit seinem eigenen Wert bei konstanter Initialisierung initialisiert wird, die 0 aufgrund Null Initialisierung sein wird.

Ist das wirklich der Fall? Klirren accepts this code während gcc produces a diagnostic:

error: the value of 'x' is not usable in a constant expression 
constexpr int x = x; 
       ^
+2

Es ist nie undefiniertes Verhalten. –

+0

@ T.C. Als ich UB erwähnte, dachte ich an [diesen Fall] (http://stackoverflow.com/q/14935722/1708801) und die dazugehörige [C++ 14 Version hier] (http://stackoverflow.com/q/ 23415661/1708801). Ich hatte ursprünglich auf sie in der Frage verwiesen, fühlte mich aber, als würde es weniger deutlich machen. –

+3

Sicher, aber in diesem Zusammenhang ist alles, was UB wäre, kein konstanter Ausdruck, wodurch die Initialisierung schlecht gebildet wird. –

Antwort

23

Diese geklärt wurde und schlecht gebildet durch defect report 2026: Zero-initialization and constexpr gemacht, die fragt:

Nach 3.6.2 [basic.start.init] Absatz 2

Variablen mit statischer Speicherdauer (3.7.1 [basic.stc.static]) oder Thread-Speicherdauer (3.7.2 [basic.stc.thread]) müssen null initialisiert sein (8.5 [dcl.init]) bevor irgendeine andere Initialisierung stattfindet.

Gilt dies auch für die konstante Initialisierung? Zum Beispiel sollte das Folgende wohlgeformt sein und sich auf die angenommene Zero-Initialisierung stützen, die der konstanten Initialisierung vorausgeht?

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

Die Notiz vor der geplanten Auflösung sagt:

CWG vereinbart, dass eine konstante Initialisierung sollte so geschieht statt Null Initialisierung in diesen Fällen in Betracht gezogen werden, so dass die Erklärungen schlecht ausgebildet.

und die vorgeschlagene Auflösung klärt und unter vielen Änderungen, entfernt die folgende Formulierung:

Variables mit statischer Speicherdauer (3.7.1) oder Fadenspeicherdauer (3.7.2) wird null- sein initialisiert (8.5) bevor irgendeine andere Initialisierung stattfindet. [...]

und fügt den folgenden Wortlaut:

Wenn konstante Initialisierung nicht durchgeführt wird, eine Variable mit statischer Speicherdauer (3.7.1 [basic.stc.static]) oder Thread-Speicherdauer (3.7.2 [basic.stc.thread]) wird auf Null initialisiert (8.5 [dcl.init]). [...]

Es ist eine große Veränderung, benennt es [basic.start.init]-[basic.start.static] und erstellt einen neuen Abschnitt [basic.start.dynamic ] und ändert [stmt.dcl]