2014-10-23 10 views
5

Per quali tipi di contenitori di libreria standard sono i typedef all'interno del contenitore, non ciò che si vorrebbe pensare ingenuamente?C++ quando typedef in contenitori di librerie standard non è quello che ci si aspetterebbe?

In codice, a quali condizioni il tipo T e il contenitore container_type fare le seguenti verifiche statiche non tutti restituiscono true:

typedef double T; 
typedef std::vector<T> container_type; 

std::is_same<typename container_type::value_type, T>::value; 
std::is_same<typename container_type::reference, T&>::value; 
std::is_same<typename container_type::const_reference, T const&>::value; 
std::is_same<typename container_type::pointer, T*>::value; 
std::is_same<typename container_type::const_pointer, T const*>::value; 

So solo di std::vector<bool>::reference che non è bool& (e probabilmente questo è lo stesso per la versione const).

Ci sono altri?

+5

Per 'map' e' unordered_map', non c'è 'T'. 'value_type' è' pair '. –

+0

@Mike Seymour: certo, ma penso che tu abbia ricevuto la domanda – davidhigh

risposta

6

Per qualsiasi contenitore contenente oggetti di tipo T, lo standard (C++ 11 23.2.1/4) richiede che:

  • container_type::value_type è T
  • container_type::reference è un lvalue di T, cioè un T&
  • container_type::const_reference è un Ivalue const di T, cioè un const T&

pointer e const_pointer non fanno parte di alcuno dei requisiti Container, sono semplicemente dei typedef di convenienza nei contenitori standard, prelevati dall'allocatore del contenitore.

Quindi, per rispondere alla tua domanda:

value_type, reference e const_reference deve essere come ci si aspetta, altrimenti il ​​contenitore non soddisfa i requisiti Container. Si noti che questo significa (ad esempio Herb Sutter points out), che std::vector<bool> è non un contenitore nel senso standard.

pointer e const_pointer sono typedefs ai tipi allocatore, in modo che quando si ha un contenitore con allocatore A, saranno differire dai T* e T const* ogniqualvolta std::allocator_traits<A>::pointer e std::allocator_traits<A>::const_pointer differiscono da loro.

e di affrontare direttamente la questione di quale contenitori standard soddisfano questi requisiti: Container

  • std::array<T> fa, per 23.3.2.1/3 (con alcune eccezioni che non incidono le typedef in questione)
  • std::deque<T> fa, per 23.3.3.1/2
  • std::forward_list<T> fa, per 23.3.4.1/2 (con alcune eccezioni che non influiscono le typedef in questione)
  • std::list<T> doe s, per 23.3.5.1/2
  • std::vector<T> fa (per T diverso bool), per 23.3.6.1/2 (con alcune eccezioni che non influiscono le typedef in questione)
  • std::set<T> fa, al 23,4. 6.1/2
  • std::multiset<T> fa, per 23.4.7.1/2
  • std::unrdered_set<T> fa, per 23.5.6.1/2
  • std::unordered_multiset<T> fa, per 23.5.7.1/2
  • std::basic_string<T> contiene i typedef in questione (a i tipi corretti) come in 21.4./5, anche se lo standard non lo richiede esplicitamente per soddisfare i requisiti Container. Notare che value_type dipende dai tratti di carattere, quindi std::basic_string<T, MyTraits> può avere value_type diverso da T.

std::[unorderd_][multi]map non si qualificano, perché prendono più di un parametro di template obbligatorio e li usano per sintetizzare value_type.

std::valarray<T> non si qualifica perché fornisce solo il typef value_type e nessuno degli altri.

+0

grazie, bella risposta, ma solleva immediatamente una domanda correlata: per quali combinazioni di 'container_type' e' T' è 'container_type ' not a 'Container'? Solo per 'std :: vector '? – davidhigh

+0

@davidhigh e quando sarebbe legale per gli utenti specializzare un container std da fare, beh, quale che sia? ;) – Yakk

+0

@Yak: scusate, avrei dovuto dirlo, ho fatto riferimento ai tipi di POD per 'T'. – davidhigh

Problemi correlati