Мне интересно,
std::is_unsigned<bool>::value
хорошо определен в соответствии со стандартом или нет?
Я задаю вопрос, потому что typename std::make_unsigned<bool>::type
не определен.
Мне интересно,
std::is_unsigned<bool>::value
хорошо определен в соответствии со стандартом или нет?
Я задаю вопрос, потому что typename std::make_unsigned<bool>::type
не определен.
Нет понятия подписи для bool
. Из [basic.fundamental]/6:
Значения типа
bool
являются либоtrue
offalse
. [Примечание. Нет типовsigned
,unsigned
,short
илиlong
bool
bool
. - end note] Значения типаbool
участвуют в интегральных акциях (4.5).
В отличие от этого подпись явно вызывается для целочисленных типов со знаком (параграф 2) и целых типов без знака (пункт 3).
Теперь для признаков is_signed
и is_unsigned
. Во-первых, черты всегда хорошо определены, но интересны только для арифметических типов. bool
является арифметическим типом, а is_signed<T>::value
определяется (см. таблицу 49) как T(-1) < T(0)
. Используя правила логического преобразования и стандартные арифметические преобразования, мы видим, что это false
для T = bool
(потому что bool(-1)
есть true
, который преобразуется в 1
). Аналогично, is_unsigned<T>::value
определяется как T(0) < T(-1)
, который true
для T = bool
.
is_unsigned
определяется в [meta.unary.comp]/2 как
Если
is_arithmetic<T>::value
-true
, тот же результат, что иbool_constant<T(0) < T(-1)>::value
; в противном случаеfalse
bool
† явно является арифметическим типом (являющимся интегралом). Теперь рассмотрим [conv.bool]/1:
Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется в
false
; любое другое значение преобразуется вtrue
.
т.е. bool(0) < bool(-1)
эквивалентно false < true
, и последнее выполняется, поскольку значения повышаются до 0
и 1
соответственно.
Таким образом, is_unsigned<bool>::value
является true
(и, наоборот, is_signed
является false
), из-за того, что значения bool
ean соответствуют беззнаковым значениям 0
и 1
во время арифметических операций, Тем не менее, нет смысла оценивать подпись bool
, а тем более выполнять make_unsigned
на ней, поскольку она не представляет целые числа, а скорее состояния.
bool
, в первую очередь определяется его предложением Требование несуществующим, bool
не являющимся неполным типом ([res.on.functions ]/(2.5)) и других требований, упомянутых в [meta.rqmts] для UnaryTypeTraits. Да, он четко определен, как и любой другой унарный тип.
С++ 14 (n4140) 20.10.4/2 "Унарные типы признаков":
Каждый из этих шаблонов должен быть UnaryTypeTrait (20.10.1) с BaseCharacteristic
true_type
, если соответствующее условие истинно, иначеfalse_type
.
20.10.1/1:
В UnaryTypeTrait описывается свойство типа. Это шаблон класса, который принимает один тип шаблона аргумент и, необязательно, дополнительные аргументы, которые помогают определить описываемое свойство. Это должно быть
DefaultConstructible
,CopyConstructible
и публично и однозначно выведенные, прямо или косвенно, из его BaseCharacteristic, который является специализацией шаблонаintegral_constant
(20.10.3), с аргументами к шаблонуintegral_constant
, определяемым требованиями для конкретного описывается свойство. Имена членов BaseCharacteristic не должны быть скрыты и должны быть недвусмысленно доступны в UnaryTypeTrait.
Из этого следует, что конструкция std::is_unsigned<T>::value
должна быть хорошо определена для любого типа T
, имеет ли смысл понятие "подпись" смысл для типа или нет.
Да, это хорошо определено, и результат должен быть std::is_unsigned<bool>::value == true
Документация для std::is_signed
говорит
Если
T
- это арифметический тип с подпиской, значение константы элемента равно true. Для любого другого типа значение равно false.
Итак, если вы посмотрите std::is_arithmetic
Если T является арифметическим типом (т.е. интегральным типом или типом с плавающей запятой), значение константы элемента равно true. Для любого другого типа значение равно false.
Что в конечном итоге приводит к std::is_integral
Проверяет, является ли T интегральным типом. Предоставляет постоянное значение члена, которое равно true, если T является типом
bool
,char
,char16_t
,char32_t
,wchar_t
,short
,int
,long
,long long
или любых расширенных целочисленных типов, определенных для реализации, включая любые подписанные, неподписанные и cv-квалификационные варианты. В противном случае значение равно false.
Интересно, что есть еще одна функция std::numeric_limits::is_signed
, которая гласит
Значение
std::numeric_limits<T>::is_signed
равноtrue
для всех подписанных арифметических типовT
иfalse
для неподписанных типов. Эта константа имеет смысл для всех специализаций.
Если специализация для bool
указана как false
, что также подтверждает, что bool
считается беззнаковым.