Como observa Luc Danton, las reglas en [expr.const]/2 bloquean los intentos y dicen que no se permiten varias expresiones en constante de núcleo expresiones, entre ellos:
- un reinterpret_cast
- una operación que tendría un comportamiento indefinido [nota: en particular, [...] cierta aritmética de puntero [...] - nota final]
El La primera viñeta descarta su primer ejemplo. El segundo ejemplo se descarta por la primera bala anterior, además de la regla de [expr.cast]/4 que:
Las conversiones realizadas por [...] un reinterpret_cast
[...] se puede realizar utilizando la notación de conversión explícita de tipo. Se aplican las mismas restricciones y comportamientos semánticos.
La segunda bala se añadió por WG21 core issue 1313, y aclara que la aritmética de punteros en un puntero nulo no está permitida en una expresión constante. Esto descarta su tercer ejemplo.
Incluso si estas restricciones no se aplican a las expresiones constantes fundamentales, que todavía no sería posible inicializar un puntero constexpr
con un valor producido por emitan un número entero, ya que una variable puntero constexpr debe ser inicializado por una expresión constante dirección, que, por [expr.const]/3, debe evaluar a
la dirección de un objeto con duración de almacenamiento estático, la dirección de una función o un valor de puntero nulo.
Un entero de tipo puntero no es ninguno de estos.
g ++ aún no hace cumplir estrictamente estas reglas, pero sus lanzamientos recientes se han estado acercando a ellos, por lo que deberíamos suponer que finalmente los implementará completamente.
Si su objetivo es declarar una variable para la cual se realiza la inicialización estática, simplemente puede soltar el constexpr
- tanto clang como g ++ emitirán un inicializador estático para esta expresión. Si necesita esta expresión para ser parte de una expresión constante, por alguna razón, usted tiene dos opciones:
- reestructurar su código para que un intptr_t se pasa alrededor en lugar de un puntero, y echarlo a un tipo de puntero cuando se necesita (fuera de una expresión constante) o
- Use
__builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF
. Esta forma exacta de expresión (con __builtin_constant_p
en el lado izquierdo de un operador condicional) deshabilita la comprobación estricta de la expresión constante en los brazos del operador condicional, y es una extensión de GNU no portátil poco conocida, pero documented compatible con tanto gcc como clang.
¿Por qué necesita un constexpr aquí? ¿No es exactamente igual que const si no está utilizando una función? –
@RobertMason: Bueno, por ejemplo, si es un miembro estático de una clase, y no es constexpr, no puedo inicializarlo en línea. – HighCommander4
Tal vez una función de miembro en línea estática sería más apropiada que un miembro de datos. –