variable values bool c++ boolean language-lawyer c++14 unsigned

c++ - values - boolean variable



¿Está std:: is_unsigned<bool>:: value bien definido? (4)

Me pregunto si

std::is_unsigned<bool>::value

¿Está bien definido según el estándar o no?

Hago la pregunta porque typename std::make_unsigned<bool>::type no está bien definido.


No hay un concepto de firma para bool . De [basic.fundamental] / 6:

Los valores de tipo bool son true o false . [ Nota : no hay tipos o valores de bool signed , unsigned , short o long . - nota final ] Los valores de tipo bool participan en promociones integrales (4.5).

Por el contrario, la firma se llama explícitamente para los tipos enteros con signo (párrafo 2) y los tipos enteros sin signo (párrafo 3).

Ahora para los rasgos is_signed e is_unsigned . En primer lugar, los rasgos siempre están bien definidos, pero solo son interesantes para los tipos aritméticos. bool es un tipo aritmético, y is_signed<T>::value se define (ver Tabla 49) como T(-1) < T(0) . Al usar las reglas de conversión booleana y conversiones aritméticas estándar, vemos que esto es false para T = bool (porque bool(-1) es true , lo que se convierte en 1 ). De manera similar, is_unsigned<T>::value se define como T(0) < T(-1) , lo cual es true para T = bool .


Sí, está bien definido y el resultado debe ser std::is_unsigned<bool>::value == true

La documentación para std::is_signed dice

Si T es un tipo aritmético con signo , proporciona al miembro un valor constante igual a verdadero. Para cualquier otro tipo, el valor es falso.

Entonces, si nos fijamos en std::is_arithmetic

Si T es un tipo aritmético (es decir, un tipo integral o un tipo de coma flotante ), proporciona al miembro un valor constante igual a verdadero. Para cualquier otro tipo, el valor es falso.

Lo que finalmente conduce a std::is_integral

Comprueba si T es un tipo integral. Proporciona el valor constante del miembro que es igual a verdadero, si T es el tipo bool , char , char16_t , char32_t , wchar_t , short , int , long , long long o cualquier tipo de entero extendido definido por la implementación, incluidos los firmados, sin firmar, y variantes calificadas por cv. De lo contrario, el valor es igual a falso.

Curiosamente, hay otra función std::numeric_limits::is_signed que establece

El valor de std::numeric_limits<T>::is_signed es true para todos los tipos aritméticos con signo T y false para los tipos sin signo. Esta constante es significativa para todas las especializaciones.

Donde la especialización para bool aparece como false , lo que también confirma que bool se considera sin signo.


Sí, está bien definido, como cualquier otro rasgo de tipo unario.

C ++ 14 (n4140) 20.10.4 / 2 Mandatos de "rasgos de tipo unario":

Cada una de estas plantillas será un UnaryTypeTrait (20.10.1) con una BaseCharacteristic de true_type si la condición correspondiente es verdadera; de lo contrario, false_type .

20.10.1 / 1:

UnaryTypeTrait describe una propiedad de un tipo. Será una plantilla de clase que tome un argumento de tipo de plantilla y, opcionalmente, argumentos adicionales que ayuden a definir la propiedad que se describe. Será DefaultConstructible , CopyConstructible , y se CopyConstructible pública e inequívocamente, directa o indirectamente, de su BaseCharacteristic, que es una especialización de la plantilla integral_constant (20.10.3), con los argumentos de la plantilla integral_constant determinados por los requisitos para la propiedad particular siendo descrito Los nombres de miembros de BaseCharacteristic no se ocultarán y estarán disponibles sin ambigüedades en UnaryTypeTrait.

De esto se deduce que la construcción std::is_unsigned<T>::value debe estar bien definida para cualquier tipo T , ya sea que el concepto de "firma" tenga sentido para el tipo o no.


is_unsigned se define en [meta.unary.comp] / 2 como

Si is_arithmetic<T>::value es true , el mismo resultado que
bool_constant<T(0) < T(-1)>::value ; de lo contrario, false

bool es claramente un tipo aritmético (siendo integral). Ahora considere [conv.bool] / 1:

Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en false ; cualquier otro valor se convierte en true .

Es decir, bool(0) < bool(-1) es equivalente a false < true , y este último se cumple ya que los valores se promueven a 0 y 1 , respectivamente.

Por is_unsigned<bool>::value tanto, is_unsigned<bool>::value es true (y, por el contrario, is_signed es false ), debido al hecho de que los valores bool ean corresponden a los valores sin signo 0 y 1 durante las operaciones aritméticas. Sin embargo, realmente no tiene sentido evaluar la firma de bool , mucho menos realizar make_unsigned en él, ya que no representa números enteros, sino estados.

: El hecho de que esta plantilla es aplicable a bool en primer lugar está determinada por su cláusula de requisito que no existe, bool no es un tipo incompleto ([res.on.funciones] / (2.5)) y no hay otros requisitos mencionado en [meta.rqmts] para UnaryTypeTraits .