NO, non è sempre vero. E 'comunque un po' più complicato di quanto possa sembrare a prima vista:
In principio, vediamo che cosa std::string
è (21,3/1):
L'intestazione <string>
definisce il modello basic_string
classe per la manipolazione sequenze variando lunghezza di oggetti char-like e quattro typedef, string
, u16string
, u32string
e wstring
, che nome specializzazioni basic_string<char>
, basic_string<char16_t>
, basic_string<char32_t>
e basic_string<wchar_t>
, respectiv ely.
iniziare con 21,4/5:
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
typedef typename allocator_traits<Allocator>::size_type size_type;
static const size_type npos = -1;
// [other members omitted]
};
nota che mentre npos
inizializzato con -1
, il suo tipo dipende Allocator::size_type
, il che significa che senza ulteriori conoscenze, non possiamo semplicemente presumere che string::npos == -1
sarà anche compilato.
Ora, come string
utilizza l'allocatore di default (il parametro di modello ha il valore di default nella typedef fornito dalla libreria standard, dopo tutto), cerchiamo di controllare 20.6.9:
typedef size_t size_type;
Ora, possiamo essenzialmente riscrivere la domanda come: size_t(-1) == -1
. Quello che succede ora dipende dal tipo delle sottoespressioni: Il lato sinistro ha ovviamente il tipo size_t
, mentre il lato destro è un valore letterale intero, che ha il tipo int
, se scritto in questo modo (senza ulteriori qualificazioni).
Il risultato è true
se size_t
è almeno grande quanto int
(per gli standard fanatici: ha una più grande grado di conversione intero come definito nella 4.13). In caso contrario, il lato sinistra otterrà promosso int
, causando un confronto come 0xFFFF == -1
(per size_t
essere uint16_t
e int
avente 32 bit), che è false
.
Si noti che mentre i sistemi a 16 bit stessi non sono più molto comuni (ad eccezione di alcuni residui in fattori di forma molto piccoli), int
non è limitato a 32 bit dallo standard. Un compilatore che punta su x86_64 con bit size_t
e 128 bit int
sarebbe tecnicamente conforme.
Tutte le virgolette sono dello standard C++ 11 (ISO/IEC 14882: 2011).
Come domanda di follow-up, prima convertendo il tipo di lato sinistro in un tipo firmato, si garantisce l'espressione? Ad esempio: '(signed size_t) std :: string :: npos == -1' – randomusername
@randomusername Questa conversione ha come risultato un comportamento indefinito, poiché il valore di' npos' è troppo grande. Basta fare quanto segue: 'std :: string :: npos == std :: string :: size_type (-1)' e stai bene. –