Является ли std:: is_unsigned <bool>:: значение определено?
Мне интересно,
std::is_unsigned<bool>::value
хорошо определен в соответствии со стандартом или нет?
Я задаю вопрос, потому что typename std::make_unsigned<bool>::type
не определен.
Ответы
Ответ 1
Нет понятия подписи для bool
. Из [basic.fundamental]/6:
Значения типа bool
являются либо true
of false
. [Примечание. Нет типов 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
.
Ответ 2
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.
Ответ 3
Да, он четко определен, как и любой другой унарный тип.
С++ 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
, имеет ли смысл понятие "подпись" смысл для типа или нет.
Ответ 4
Да, это хорошо определено, и результат должен быть 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
считается беззнаковым.