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
sontrue
ofalse
. [ Nota : no hay tipos o valores debool
signed
,unsigned
,short
olong
. - nota final ] Los valores de tipobool
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
estrue
para todos los tipos aritméticos con signoT
yfalse
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 seCopyConstructible
pú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_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
estrue
, 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
.