2016-01-05 16 views

risposta

62

Non esiste un concetto di firma per bool. Da [basic.fundamental]/6:

Valori di tipo bool sono o true di false. [Nota: non ci sono signed, unsigned, short o longbool tipi o valori. - nota finale] I valori di tipo bool partecipano alle promozioni integrali (4.5).

Al contrario, signedness è esplicitamente chiamato fuori per il tipi interi firmati (paragrafo 2) e tipi unsigned interi (paragrafo 3).

Ora per i tratti is_signed e is_unsigned. Prima di tutto, i tratti sono sempre ben definiti, ma solo interessanti per i tipi aritmetici. bool è un tipo aritmetico e is_signed<T>::value è definito (vedere Tabella 49) come T(-1) < T(0). Utilizzando le regole della conversione booleana e delle conversioni aritmetiche standard, vediamo che questo è false per T = bool (perché bool(-1) è true, che viene convertito in 1). Allo stesso modo, is_unsigned<T>::value è definito come T(0) < T(-1), ovvero true per T = bool.

22

is_unsigned è definito in [meta.unary.comp]/2 come

Se is_arithmetic<T>::value è true, lo stesso risultato
bool_constant<T(0) < T(-1)>::value; altrimenti, false

bool è chiaramente un tipo aritmetico (essendo solidale). Consideriamo ora [conv.bool]/1:

valore zero, il valore del puntatore nullo, o nullo valore del puntatore membro è convertito false; qualsiasi altro valore viene convertito in true.

I.e. bool(0) < bool(-1) equivale a false < true e quest'ultimo vale poiché i valori vengono promossi a 0 e 1, rispettivamente.

Così is_unsigned<bool>::value è true (e, viceversa, è is_signedfalse), a causa del fatto che i valori bool ean corrispondono ai valori senza segno 0 e 1 durante le operazioni aritmetiche. Tuttavia, non ha senso valutare la firma di bool, tanto meno eseguire make_unsigned su di esso, poiché non rappresenta numeri interi, ma piuttosto stati.


: Il fatto che questo modello è applicabile bool in primo luogo è determinata dalla sua clausola requisito essendo inesistente, bool non essendo un tipo incompleto ([res.on.functions]/(2.5)) e nessun altro requisito è menzionato in [meta.rqmts] per UnaryTypeTraits.

+0

Leggero nitpick: "i valori sono promossi a 0 e 1, rispettivamente" non è corretto al 100%. Le regole di conversione (4.12) dicono che un valore intero zero viene convertito in 'false' e ​​_anche altro valore_viene convertito in' true' (nessun 1 è coinvolto ovunque). Lo standard definisce anche una conversione in intero dove 'true' convertirà _ in 1, e' false' convertirà _ in 0, tuttavia non dirà nulla di ciò che i valori in realtà sono _are_. Per quanto ne sappiamo, 'true' potrebbe essere 67 e' false' potrebbe essere 172 (questo non è quasi mai il caso, ma secondo lo standard potrebbe essere). Ancora +1. – Damon

+2

@Damon Aspetta, non vedo come le tue osservazioni si applicano alla mia frase. Ho fatto riferimento ai valori promossi a 0 e 1 durante la promozione integrale che viene applicata durante la valutazione di 'false Columbo

+0

Quello che voglio dire è che 'bool (-1)' converte in 'true' subito, non c'è promozione integrale a 1 coinvolto. Qualsiasi valore diverso da zero converte immediatamente in 'true'. Quindi, 'bool (0) Damon

9

Sì, è ben definito e il risultato dovrebbe essere std::is_unsigned<bool>::value == true

La documentazione per std::is_signed dice

Se T è un tipo aritmetico firmato, fornisce agli Stati valore costante pari vero. Per qualsiasi altro tipo, il valore è falso.

Allora, se si guarda a std::is_arithmetic

Se T è un tipo aritmetico (cioè, un tipo intero o un tipo in virgola mobile), fornisce il valore della costante membro paritario vero. Per qualsiasi altro tipo, il valore è falso.

che porta infine std::is_integral

Verifica se T è un tipo integrale. Fornisce il valore costante elemento che è uguale a true, se T è il tipo bool, char, char16_t, char32_t, wchar_t, short, int, long, long long o qualsiasi tipi interi estesi attuazione definiti, compresi eventuali firmata, senza segno e varianti qualificate per CV. Altrimenti, il valore è uguale a falso.

interessante notare che v'è un'altra funzione che indica std::numeric_limits::is_signed

Il valore di std::numeric_limits<T>::is_signed è true per tutti i tipi aritmetici firmati T e false per i tipi senza segno. Questa costante è significativa per tutte le specializzazioni.

Qualora la specializzazione per bool è elencato come false, che conferma anche che bool è considerato senza segno.

+0

cppreference non è una fonte autorevole, ma solo un'interpretazione. OP aveva bisogno di un'informazione autorevole - lo standard. –

+2

@IlyaPopov Nella maggior parte dei casi cppreference cita lo standard verbatim e indica quale versione (C++ 03/11/14/etc) si applica a. – CoryKramer

+0

Sì, si chiama cpp _reference_ per un motivo. A differenza di cplusplus.com. – edmz

10

Sì, è ben definito, come qualsiasi altro tratto di tipo unario.

C++ 14 (n4140) 20.10.4/2 "di tipo tratti unari" mandati:

Ciascuno di questi modelli saranno un UnaryTypeTrait (20.10.1) con un BaseCharacteristic di true_type se la condizione corrispondente è vera, altrimenti false_type.

20.10.1/1:

Un UnaryTypeTrait descrive una struttura di tipo. Deve essere un modello di classe che accetta un argomento modello e, facoltativamente, argomenti aggiuntivi che consentono di definire la proprietà descritta. Sarà DefaultConstructible, CopyConstructible, e pubblicamente e senza ambiguità derivata, direttamente o indirettamente, dalla sua BaseCharacteristic, che è una specializzazione del modello integral_constant (20.10.3), con gli argomenti al modello integral_constant determinato dal requisiti per la particolare proprietà descritta. I nomi dei membri di BaseCharacteristic non devono essere nascosti e devono essere disponibili in modo non ambiguo in UnaryTypeTrait.

Da ciò segue che il costrutto std::is_unsigned<T>::value deve essere ben definita per ogni tipo T, se il concetto di "signedness" senso per il tipo o meno.

Problemi correlati