not dev declared c++ gcc clang nullptr

c++ - dev - clang vs gcc



¿Es nullptr_t un tipo constructible por defecto? (2)

No puedo decir del estándar C ++ 11 si nullptr_t tiene un constructor predeterminado. En otras palabras, ¿es válido lo siguiente ?:

nullptr_t n;

GCC y VC ++ permiten el código anterior, pero clang no lo hace. No puedo encontrar nada en el Estándar que especifique que no tenga un constructor predeterminado, y lo que puedo encontrar sugiere que debería hacerlo. Esto me importa porque estoy escribiendo una implementación básica alternativa de nullptr para el soporte del compilador anterior y necesito saber si necesito darle un constructor predeterminado.


Lo que dice la norma

La norma dice (18.2)

nullptr_t se define de la siguiente manera:

namespace std { typedef decltype(nullptr) nullptr_t; }

El tipo para el que nullptr_t es un sinónimo tiene las características descritas en 3.9.1 y 4.10.

Donde 3.9.1 básicamente dice que debe ser del mismo tamaño que void* y 4.10 especifica las reglas de conversión para nullptr .

Edit: 3.9.9 además, explícitamente establece que nullptr_t es un tipo escalar, lo que significa que se aplican las reglas de inicialización esperadas para los tipos incorporados de 8.5:

  • Default-initialization ( nullptr_t n; ), que deja el valor de n indefinido. Como Johannes Schaub señaló correctamente, esto compila bien con la versión más reciente de Clang.
  • Inicialización del valor ( nullptr_t n = nullptr_t(); ), que inicializa n a 0.

Este comportamiento es idéntico a, por ejemplo, int , por lo que nullptr_t es definitivamente construible por defecto. La pregunta interesante aquí es: ¿Qué significa que nullptr_t tenga un valor indefinido? Al final del día, solo hay un valor significativo significativo para nullptr_t , que es nullptr . Además, el tipo en sí solo se define a través de la semántica del literal nullptr . ¿Estas semánticas todavía aplican para un valor unitario?

Por qué esa pregunta no importa en la práctica

No desea declarar una nueva variable de tipo nullptr_t . La única semántica significativa de ese tipo ya se expresa a través del literal nullptr , por lo que cada vez que use su variable personalizada de tipo nullptr_t , también puede usar nullptr .

Lo que importa en la práctica.

La única excepción a esto proviene del hecho de que puede tomar parámetros de plantilla que no sean de tipo nullptr_t . Para este caso, es útil saber qué valores se pueden convertir a nullptr_t , que se describe en 4.10:

Una constante de puntero nula es una expresión constante constante (5.19) prvalue de tipo entero que se evalúa a cero o un prvalue de tipo std::nullptr_t . [...] Una constante de puntero nulo de tipo integral se puede convertir a un valor predeterminado de tipo std::nullptr_t .

Lo que básicamente hace justo lo que esperas: puedes escribir

nullptr_t n = 0; // correct: 0 is special

pero no

nullptr_t n = 42; // WRONG can''t convert int to nullptr_t

Tanto gcc 4.6 como Clang SVN lo hacen bien.


Si bien nullptr es una nueva adición al lenguaje en sí, std::nullptr_t es solo un alias de un tipo sin nombre, el alias declarado en cstddef esta manera:

typedef decltype(nullptr) nullptr_t;

Si bien nullptr_t , siendo typedef y no una palabra clave de idioma, no aparece como un tipo fundamental, se especifica que se comporte como un tipo fundamental (y no, por ejemplo, como un tipo de puntero o un tipo de clase). Por lo tanto, no tiene un constructor predeterminado, pero aún puede declarar una variable como lo ha hecho. Su variable no está inicializada y me pregunto qué uso podría tener y qué mensaje de error recibió exactamente de clang .

Véase también here .