and c++ language-lawyer c++14 constexpr c++17

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; ^