Кто-нибудь может объяснить, почему

#include <iostream>
#include <type_traits>
using namespace std;
enum E : signed int { a=-1, b = 1,};
int main() {
    std::cout << std::boolalpha;
    cout << "strong typed enum E:int should be signed, but is_signed returns " 
    << is_signed<E>() << "\n";
    return 0;
}

Std :: is_signed <> не делает, что написано на жестяной коробке? Благодаря...

6
x y 27 Окт 2015 в 12:22

2 ответа

Лучший ответ

Если мы посмотрим на документацию для is_signed, она говорит:

Если T является арифметическим типом со знаком , предоставляет значение константы элемента, равное true. Для любого другого типа значение false.

И перечисление не является арифметическим типом, поэтому результат должен быть ложным. Из проекта стандартного раздела C ++ 11 3.9.1 Основные типы [basic.fundamental]:

[...] Целые и плавающие типы вместе называются арифметическими типами [...]

Вы можете получить базовый тип для перечисления, используя std ::atabases_type, а затем применить std::is_signed к этому типу.

7
Shafik Yaghmour 28 Окт 2015 в 00:08

Для записи, чтобы узнать, является ли базовый тип строго типизированного перечисления (то есть не само перечисление, которое невозможно проверить на наличие подписи) подписан или нет, вы можете запросить std::underlying_type<E>::type:

std::is_signed<std::underlying_type<E>::type>::value

Или определите свою собственную черту:

#include <type_traits>

template <typename T>
struct identity { using type = T; };

template <typename T>
struct is_signed
    : std::is_signed<typename std::conditional<std::is_enum<T>::value
                                             , std::underlying_type<T>
                                             , identity<T>>::type::type> {};

ДЕМО

2
Community 23 Май 2017 в 11:58