c++ - and - Autoinicialización de una variable constexpr estática, ¿está bien formada?
constexpr in c++ (1)
Esto se aclaró y quedó mal formado por el informe de defectos 2026: Cero-inicialización y constexpr que pregunta:
De acuerdo con 3.6.2 [basic.start.init] párrafo 2,
Las variables con duración de almacenamiento estático (3.7.1 [basic.stc.static]) o duración de almacenamiento de subprocesos (3.7.2 [basic.stc.thread]) se inicializarán con cero (8.5 [dcl.init]) antes de cualquier otra inicialización tiene lugar
¿Esto se aplica también a la inicialización constante? Por ejemplo, ¿debería estar bien formado lo siguiente, basándose en la presunta inicialización cero que precede a la inicialización constante?
constexpr int i = i; struct s { constexpr s() : v(v) { } int v; }; constexpr s s1;
La nota antes de la resolución propuesta dice:
El CWG acordó que la inicialización constante debe considerarse como que ocurre en lugar de una inicialización cero en estos casos, lo que hace que las declaraciones no estén bien formadas.
y la resolución propuesta aclara y, entre muchos cambios, elimina la siguiente redacción:
Las variables con duración de almacenamiento estático (3.7.1) o duración de almacenamiento de subprocesos (3.7.2) deben inicializarse con cero (8.5) antes de que se produzca cualquier otra inicialización. [...]
y añade la siguiente redacción:
Si no se realiza la inicialización constante, una variable con duración de almacenamiento estático (3.7.1 [basic.stc.static]) o duración de almacenamiento de subprocesos (3.7.2 [basic.stc.thread]) se inicializa con cero (8.5 [dcl. en eso]). [...]
Es un cambio grande, cambia el nombre de [basic.start.init] a [basic.start.static] y crea una nueva sección [basic.start.dynamic] y modifica [stmt.dcl]
Dada la siguiente declaración en el espacio de nombres global:
constexpr int x = x;
¿Está bien formado?
El borrador de la sección 3.6.2
de la norma C ++ 14 [basic.start.init] dice:
Las variables con duración de almacenamiento estático (3.7.1) o duración de almacenamiento de subprocesos (3.7.2) deben inicializarse con cero (8.5) antes de que se produzca cualquier otra inicialización. [...]
Lo que parece hacer que el ejemplo esté bien definido es que x
se inicializa con su propio valor durante la inicialización constante, que será 0
debido a la inicialización cero.
¿Es este realmente el caso? Clang acepta este código mientras que gcc produce un diagnóstico :
error: the value of ''x'' is not usable in a constant expression
constexpr int x = x;
^