2012-08-11 12 views
6

È questo C++ valido (considerando l'ultimo standard)? Ricevo errori di compilazione con clang/libC++ near-top-of-tree su Ubuntu 12.04. Se dovrebbe essere valido, invierò la mail alla lista clang-dev con i messaggi di errore e così via.È unordered_set <reference_wrapper <Ty>> valido?

#include <functional> 
#include <unordered_set> 

struct X 
{ 
    int i; 
}; 

void f() 
{ 
    std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; 

    // Do stuff with setOfReferencesToX 
} 

** Per inciso, sono stanco delle qualifiche che la domanda/risposta è specifico per l'ultimo standard. Potrebbe la comunità C++ nel suo complesso, per favore inizia a qualificare cose che sono specifiche del vecchio standard, invece? Il nuovo standard è uscito da circa un anno.

+1

+1 per la nota finale. – Griwes

+0

"Potrebbe la comunità C++ nel suo complesso, per favore inizia a qualificare cose che sono specifiche del vecchio standard, invece?" No. Dato il numero enorme di utenti che non sono in grado di eseguire l'aggiornamento a un compilatore con supporto C++ 11 più completo, per non parlare della popolarità di una certa famiglia di compilatori che sta aggiornando lentamente il proprio supporto C++ 11, il C++ sta andando significa C++ 03 per almeno un altro anno se non due. E non dimentichiamo che né GCC né Clang rivendicano la piena conformità a C++ 11. Il futuro non è il presente e fingere che sia non lo farà. –

risposta

8

Il problema non è specifico per std::reference_wrapper<T>, ma piuttosto per il tipo X stesso.

Il problema è che std::unordered_set richiede la definizione dei funtori di hashing e di uguaglianza per std::reference_wrapper<X>. È possibile passare il functor hash come secondo parametro template.

Ad esempio, questo dovrebbe funzionare:

#include <functional> // for std::hash<int> 

struct HashX { 
    size_t operator()(const X& x) const { 
    return std::hash<int>()(x.i);  
    } 
}; 

e poi

std::unordered_set<std::reference_wrapper<X>, HashX> setOfReferencesToX; 

Un'altra opzione è quella di fare una specializzazione per std::hash<X>:

namespace std { 
template <> 
struct hash<X> { 
    size_t operator()(const X& x) const { 
    return std::hash<int>()(x.i);  
    } 
}; 
} 

Questo permette di evitare in modo esplicito specificando il secondo argomento del modello:

std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; 

Per quanto riguarda il confronto di uguaglianza, si può risolvere questo problema fornendo un operatore di uguaglianza per la classe X:

struct X 
{ 
    bool operator==(const X& rhs) const { return i == rhs.i; } 
    int i; 
}; 

caso contrario, è possibile definire il proprio funtore e passarlo come argomento terzo modello.

+0

Non specializzare 'std :: hash' è un po 'più semplice? – Griwes

+0

Lo farebbe, se sei disposto a mettere cose nello spazio dei nomi 'std'. – juanchopanza

+0

Non penso che dovrebbe essere qualificato come "mettere roba in' std' ", in quanto è una semplice specializzazione ... – Griwes

Problemi correlati