2011-11-18 8 views
8

Voglio definire std::tr1::hash<boost::tuple<A,B,C> >. Ma ottengo un errore che non appare quando fornisco un'istanza completa. Ecco il codiceUtilizzo di boost :: tuple in tr1 :: hash

namespace std{ 

namespace tr1{ 
template<typename A, typename B, typename C> 
struct hash<boost::tuple<A,B,C> >{ 
    size_t operator()(const boost::tuple<A,B,C> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.get<0>()); 
     boost::hash_combine(seed, t.get<1>()); 
     boost::hash_combine(seed, t.get<2>()); 
     return seed; 
    } 
}; 

template<> 
struct hash<boost::tuple<int,int,int> >{ 
    size_t operator()(const boost::tuple<int,int,int> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.get<0>()); 
     boost::hash_combine(seed, t.get<1>()); 
     boost::hash_combine(seed, t.get<2>()); 
     return seed; 
    } 
}; 
} 
} 

Il primo pezzo dà questo errore

unordered.hpp: In member function 'size_t std::tr1::hash<boost::tuples::tuple<A, B, C, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >::operator()(const boost::tuples::tuple<A, B, C, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>&) const': 
unordered.hpp:12: error: expected primary-expression before ')' token 
unordered.hpp:13: error: expected primary-expression before ')' token 
unordered.hpp:14: error: expected primary-expression before ')' token 

e la seconda compila bene. Cosa c'è che non va nel primo modello? Sto usando gcc 4.3.4.

+0

Non è 'std :: hash' una funzionalità di C++ 11? In tal caso puoi usare anche 'std :: tuple'. Credo che manchi una parola chiave 'typename'. – AJG85

+0

Penso che 'boost :: hash' sia già definito per' boost :: tuple's. Se stai usando la libreria standard, usa anche 'std :: tuple'! –

+0

@ AJG85 Sto usando gcc 4.3.4 dove 'hash' è ancora in' tr1' e 'tuple' è solo in boost. –

risposta

8

È necessario utilizzare la parola chiave .template:

template<typename A, typename B, typename C> 
struct hash<boost::tuple<A,B,C> >{ 
    size_t operator()(const boost::tuple<A,B,C> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.template get<0>()); 
     boost::hash_combine(seed, t.template get<1>()); 
     boost::hash_combine(seed, t.template get<2>()); 
     return seed; 
    } 
}; 

Ciò è necessario perché il tipo di t dipende da tre paramaters modello (e così t è a seconda del tipo), e get<0> è il nome di una specializzazione template. Dallo standard C++ - §14.2/4:

Quando il nome di una specializzazione del modello membro viene visualizzato dopo. oppure -> in un'espressione postfix ... e l'espressione dell'oggetto dell'espressione postfix è dipendente dal tipo ... il nome del modello membro deve essere preceduto dal modello di parole chiave. ...

Questo requisito esiste per consentire l'analisi dei modelli prima che gli argomenti del tipo siano noti.

Ad esempio, si consideri:

f . set <0> (2 == 3) 

Senza la regola .template, questo potrebbe interpretato come due cose diverse:

//A call to an instantiation of a member function template 
//in this case equivalent to f.template set<0>(false) 
f.set<0>(2 == 3) 
//A series of comparison operations, in this case equivalent to 
//f.set < 0 
f.set <0> (2 == 3) 

Le norme attuali consentono f . set <0> (2 == 3) essere inequivocabilmente analizzato come una serie di confronto operazioni. Significano anche che t.get<0>() viene analizzato come t.get <0>(). Lo expected primary-expression è destinato a essere nello () vuoto.

6

Non ho tempo di controllare le cose, ma mi aspetto sia

std::get<0>(t) 

o

boost::get<0>(t) 

invece di t.get<0>()

farequalificarsi get() anche se stai "usando" spazi dei nomi, o ADL ti danneggerà male quando mischi librerie come questa . Vedere What are the pitfalls of ADL?

+0

Infatti, usando' boost :: get' ha funzionato. Perché? –

+0

Vedere http://stackoverflow.com/questions/2958648/what-are-the-pitfalls-of-adl e minori forse le differenze di interfaccia tra std :: tuple e boost :: tuple. So che ci sono differenze anche per std :: basic_regex <> – sehe

Problemi correlati