c++ - palabra - porque la acetona es mas volatil que el agua
¿Se puede combinar constexpr con volátil? (2)
Citando N4140 [dcl.constexpr] / 9:
Un especificador
constexpr
utilizado en una declaración de objeto declara que el objeto esconst
. Dicho objeto tendrá un tipo literal y se inicializará.
El tipo literal se define en [tipos de base] / 10:
Un tipo es un tipo literal si es:
(10.1) -
void
; o(10.2) - un tipo escalar; o
(10.3) - un tipo de referencia; o
(10.4) - una matriz de tipo literal; o
(10.5) - un tipo de clase (Cláusula 9) que tiene todas las siguientes propiedades:
(10.5.1) - tiene un destructor trivial,
(10.5.2): es un tipo agregado (8.5.1) o tiene al menos un constructor
constexpr
o plantilla de constructor que no es un constructor de copia o movimiento, y(10.5.3) - todos sus miembros de datos no estáticos y clases base son de tipos literales no volátiles.
El tipo escalar está en el párrafo 9:
Los tipos aritméticos (3.9.1), los tipos de enumeración, los tipos de puntero, los tipos de puntero a los miembros (3.9.2),
std::nullptr_t
y las versiones calificadas constd::nullptr_t
de estos tipos (3.9.3) se denominan colectivamente tipos escalares .
int
es aritmética, por lo que volatile int
es un tipo escalar y, por lo tanto, un tipo literal. constexpr volatile int i = 5;
Es pues una declaración bien formada.
Curiosamente, una expresión que evalúa i
no puede ser una expresión constante de núcleo, ya que aplica una conversión de valor de rvalor a un valor de tipo volátil ([expr.const] / 2). En consecuencia, las expresiones que evalúan i
no son expresiones constantes integrales ni expresiones constantes . No estoy seguro de que el constexpr
en esa declaración tenga algún efecto más allá de hacer que implícitamente const
, y (asentir a @T.C. ) requiere que su inicializador sea una expresión constante.
He reportado esto como GCC bug 65327 , veremos lo que la gente de GCC tiene que decir.
2015-03-16 Actualización: Error corregido para GCC 5.
El siguiente fragmento de código funciona bien en Clang 3.5 pero no en GCC 4.9.2:
int main()
{
constexpr volatile int i = 5;
}
con error:
error: tanto ''volatile'' como ''constexpr'' no se pueden usar aquí
Si inspecciono el ensamblaje que genera Clang, muestra 5
como se esperaba:
movl $5, -4(%rsp)
En GCC, constexpr int i = 5
se optimiza, pero la volatile int i = 5
también muestra 5
en el ensamblaje. volatile const int i = 5
compila en ambos compiladores. No es un concepto extraño para que algo sea volátil y constante al mismo tiempo.
¿Qué compilador es correcto para los estándares?
Sí, esto es válido, hubo un informe de defectos 1688: variables constexpr volátiles que se archivaron para esto, diciendo:
No parece haber un idioma en la redacción actual que indique que constexpr no se puede aplicar a una variable de tipo calificado como volátil. Además, la redacción en 5.19 [expr.const] párrafo 2 que se refiere a "un objeto no volátil definido con constexpr" podría llevar a inferir que la combinación está permitida pero que tal variable no puede aparecer en una expresión constante. ¿Cuál es la intención?
fue rechazado por no ser un defecto ( NAD ), la respuesta y el razonamiento fue:
La combinación está permitida intencionalmente y podría usarse en algunas circunstancias para forzar una inicialización constante.
Como el DR señala que una variable de este tipo no es utilizable en una expresión constante :
constexpr volatile int i = 5;
constexpr int y = i ; // Not valid since i is volatile
La sección [expr.const] / 2 incluye todos los casos que hacen que una expresión condicional no sea una expresión constante central, que incluye:
una conversión de lvalue a rvalue (4.1) a menos que se aplique a
y toda la excepción requiere:
[...] que se refiere a un objeto [...] no volátil [...]