2015-10-27 18 views
5

Qualcuno può spiegare, perchéstd :: is_signed non funziona per le enumerazioni fortemente tipizzati: int

#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 <> non fa, quello che dice sulla latta? Grazie ...

+1

Usa 'I s_signed :: type>() 'invece –

+0

@PiotrSkotnicki Grazie mille per la corretta soluzione del mio problema (non dovrebbe esserci alcun problema, se lo standard C++ sarebbe più intuitivo in questo caso ...) –

+1

Usa std :: underlying_type_t per favore –

risposta

7

Se guardiamo la documentazione per is_signed si dice:

Se T è un tipo aritmetico firmato, fornisce il valore costante pari membro vera. Per qualsiasi altro tipo, il valore è falso.

e un enum non è un tipo aritmetico, quindi il risultato dovrebbe essere falso. Dal progetto C++ 11 sezione standard 3.9.1 tipi fondamentali [basic.fundamental]:

[...] tipi integrali e galleggianti sono chiamati collettivamente aritmetica tipi [...]

È possibile ottenere il tipo sottostante per un enum utilizzando std::underlying_type e quindi applicare std::is_signed a quel tipo.

+0

Questo lo spiega - grazie, ma è una scappatoia per errori ... –

+3

@xy Questa è una questione di opinione, davvero. Io stesso sarei * estremamente * sorpreso se un tipo di enumerazione fosse segnalato come firmato. – Angew

+0

@Angew - Sono d'accordo - se sarebbe un enume "normale", ma la notazione di enumerazioni fortemente tipizzate con il **: int ** thingy è così fuorviante da pensare alla semplice derivazione da int. –

2

Per la cronaca, per sapere se il tipo sottostante di un enum fortemente tipizzato (cioè non l'enumerazione stessa, che can't be controllato per signedness) è firmato o no, è possibile interrogare std::underlying_type<E>::type:

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

o definire il proprio tratto:

#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> {}; 

DEMO

+0

Ho provato a risolvere il problema, ma non ce l'ho fatta ad arrivare ...Potete per favore darmi un'idea, cosa c'è di sbagliato con #include utilizzando namespace std; modello struct resolve_type { utilizzando resolved_type = typename condizionale :: valore, underlying_type , typename T> :: tipo; }; enum E: int {a = -1, b = 1,}; int main() { std :: cout << std :: boolalpha; cout << "is_signed enum E =" << is_signed :: resolved_type> :: valore << " <=> vero \ n "; return 0;} –

+0

@xy dovrebbe essere' utilizzando resolved_type = typename condizionale :: value, underlying_type , T> :: type; ', si ha una parola chiave' typename' ridondante –

+0

No, in VC++ 2013 si dice ancora, il tipo sottostante del mio enum non è firmato. –

Problemi correlati