2011-09-09 7 views

risposta

17

Sì. std::map ha una funzione at membro in C++ 11 con la seguente specifica (23.4.4.3/9):

T&  at(const key_type& x); 
const T& at(const key_type& x) const; 

ritorni: Un riferimento mapped_type corrispondente al x in *this.

Quantità: Un oggetto di eccezione di tipo out_of_range se questo elemento non è presente.

Complessità: logaritmico.

Si noti tuttavia che questa funzione membro è stata aggiunta in modo specifico a std::map. Non è richiesto dal più generale contenitore associativo requisito. Se stai scrivendo un codice generico che richiede un tipo di contenitore associativo, non puoi utilizzare questo nuovo at. Invece, si dovrebbe continuare a utilizzare find, che fa parte del associativa contenitore concetto , o lascia la tua aiutante non membro:

template <typename AssociativeContainer> 
typename AssociativeContainer::mapped_type& 
get_mapped_value(AssociativeContainer&       container, 
       typename AssociativeContainer::key_type const& key) 
{ 
    typename AssociativeContainer::iterator it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

template <typename AssociativeContainer> 
typename AssociativeContainer::mapped_type const& 
get_mapped_value(AssociativeContainer const&     container, 
       typename AssociativeContainer::key_type const& key) 
{ 
    typename AssociativeContainer::const_iterator it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

Oppure, se si dispone di un'implementazione che supporta i riferimenti rvalue e decltype, non avete bisogno di due overload:

template <typename AssociativeContainer, typename Key> 
auto get_mapped_value(AssociativeContainer&& container, Key const& key) 
    -> decltype(std::declval<AssociativeContainer>().begin()->second)& 
{ 
    auto const it(container.find(key)); 
    return it != container.end() ? it->second : throw std::out_of_range("key"); 
} 

(o qualcosa di simile a quello, una cosa divertente di C++ 11 è che non esistono due compilatori hanno gli stessi bug e tutti sembrano accettare leggermente diversi sottoinsiemi di valid- -e non valido - codice C++ 11)

+0

Direi che tutti i compilatori stanno chiudendo in C++ 11, ma quello potrebbe essere il mio io ottimista :) –

+1

[nitpick]. il metodo 'at' è stato aggiunto non solo a std :: map, ma anche a std :: unordered_map. Questi sono gli unici due contenitori standard per cui è sensato avere questo metodo. Anche il tuo codice funzionerà non solo per AssociateveContainers, ma anche per UnorderedAssociateveContainers, ad eccezione di set e unordered_set e, ancora, non ha senso per multimap e unordered_multimap. –

+0

@ Konstantin: Sì, forse 'UniqueAssociativeContainer' sarebbe un nome migliore per il parametro del template (' UniqueAssociativeContainerOrUniqueUnorderedAssociativeContainer' è un po 'troppo ingombrante: -O). Il punto è che ci sono contenitori diversi dai contenitori della libreria standard C++ che soddisfano i requisiti dei concetti del contenitore e che dovrebbero essere intercambiabili con i contenitori della libreria standard C++ in codice generico. Il codice che si basa sul nuovo 'at' non può fare uso di quegli altri contenitori. –

Problemi correlati