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
boolsontrueofalse. [ Nota : no hay tipos o valores deboolsigned,unsigned,shortolong. - nota final ] Los valores de tipoboolparticipan 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
Tes 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 longo 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_signedestruepara todos los tipos aritméticos con signoTyfalsepara 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_typesi 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 seCopyConstructiblepública e inequívocamente, directa o indirectamente, de su BaseCharacteristic, que es una especialización de la plantillaintegral_constant(20.10.3), con los argumentos de la plantillaintegral_constantdeterminados 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>::valueestrue, 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 entrue.
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
.