Мне интересно,
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являются либоtrueoffalse. [Примечание. Нет типовsigned,unsigned,shortилиlongboolbool. - 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 считается беззнаковым.