Potresti fare a meno di un'intestazione:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); // The shortest is my favourite.
using size_t = decltype(sizeof "anything");
Questo perché lo standard C ++ richiede:
Il risultato di sizeof
ed sizeof...
è una costante di tipo std::size_t
. [Nota: std::size_t
è definito nell'intestazione standard <cstddef>
(18.2). - nota finale]
In altre parole, lo standard richiede:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
Nota anche che va perfettamente bene fare questa typedef
dichiarazione nello std
spazio globale e nello spazio dei nomi, purché corrisponda a tutte le altre typedef
dichiarazioni dello stesso tipo (viene emesso un errore del compilatore su dichiarazioni non corrispondenti).
Questo è perché:
§7.1.3.1 Un typedef-name non introduce un nuovo tipo come fa una dichiarazione di classe (9.1) o una dichiarazione enum.
§7.1.3.3 In un dato ambito non di classe, uno typedef
specificatore può essere utilizzato per ridefinire il nome di qualsiasi tipo dichiarato in tale ambito per fare riferimento al tipo a cui si riferisce già.
Agli scettici che dicono che ciò costituisce un'aggiunta di un nuovo tipo nello spazio dei nomi std
, e tale atto è esplicitamente proibito dallo standard, e questo è UB e questo è tutto lì; Devo dire che questo atteggiamento equivale a ignorare e negare una comprensione più profonda delle questioni sottostanti.
Lo standard vieta l'aggiunta di nuove dichiarazioni e definizioni nello spazio dei nomi std
perché così facendo l'utente può fare un pasticcio con la libreria standard e sparare a tutta la gamba. Per gli scrittori standard era più facile lasciare che l'utente specializzasse alcune cose specifiche e vietare di fare qualsiasi altra cosa per buona misura, piuttosto che vietare ogni singola cosa che l'utente non dovrebbe fare e rischiare di perdere qualcosa di importante (e quella gamba). Lo hanno fatto in passato quando si richiedeva che nessun contenitore standard fosse istanziato con un tipo incompleto, mentre in realtà alcuni contenitori potevano farlo bene (vedi The Standard Librarian: Containers of Incomplete Types di Matthew H. Austern ):
... Alla fine, sembrava tutto troppo torbido e troppo poco compreso; il comitato di standardizzazione non pensava ci fosse altra scelta se non quella di dire che i contenitori STL non dovrebbero funzionare con tipi incompleti. Per buona misura, abbiamo applicato quel divieto anche al resto della libreria standard.
... In retrospettiva, ora che la tecnologia è meglio compresa, quella decisione sembra ancora fondamentalmente giusta. Sì, in alcuni casi è possibile implementare alcuni dei contenitori standard in modo che possano essere istanziati con tipi incompleti, ma è anche chiaro che in altri casi sarebbe difficile o impossibile. È stato per lo più un caso che il primo test che abbiamo provato, utilizzando std::vector
, fosse uno dei casi facili.
Dato che le regole della lingua richiedono std::size_t
di essere esattamente decltype(sizeof(int))
, fare namespace std { using size_t = decltype(sizeof(int)); }
è una di quelle cose che non infrangono nulla.
Prima di C ++ 11 non c'era decltype
e quindi non c'era modo di dichiarare il tipo di sizeof
risultato in una semplice istruzione senza coinvolgere una buona quantità di modelli. size_t
alias diversi tipi su diverse architetture di destinazione, tuttavia, non sarebbe una soluzione elegante aggiungere un nuovo tipo sizeof
predefinito solo per il risultato di , e non ci sono typedef standard incorporati. Quindi, la soluzione più portabile all'epoca era inserire l' size_t
alias di tipo in un'intestazione specifica e documentarlo.
In C ++ 11 c'è ora un modo per scrivere quell'esatto requisito dello standard come una semplice dichiarazione.