2012-08-11 8 views
6

Ist das gültige C++ (unter Berücksichtigung des neuesten Standards)? Ich erhalte mit Ubuntu 12.04 einen Kompilierfehler mit "fast-top-of-tree" clang/libC++. Wenn es gültig sein sollte, sende ich die clang-dev-Liste mit Fehlermeldungen und so weiter.Ist ungeordneter_satz <reference_wrapper <Ty>> gültig?

#include <functional> 
#include <unordered_set> 

struct X 
{ 
    int i; 
}; 

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

    // Do stuff with setOfReferencesToX 
} 

** Als beiseite, ich bin müde von der Qualifikation, dass die Frage/Antwort auf den neuesten Stand spezifisch ist. Könnte die C++ - Community als Ganzes beginnen, stattdessen Dinge zu programmieren, die spezifisch für den alten Standard sind? Der neuere Standard ist seit etwa einem Jahr nicht mehr verfügbar.

+1

+1 für die Endnote. – Griwes

+0

"Könnte die C++ - Community als Ganzes beginnen, stattdessen Dinge zu programmieren, die spezifisch für den alten Standard sind?" Nein. Angesichts der schieren Anzahl von Benutzern, die nicht in der Lage sind, auf einen Compiler mit vollständigerer C++ 11-Unterstützung zu aktualisieren, ganz zu schweigen von der Beliebtheit einer bestimmten Compilerfamilie, die nur langsam ihre C++ 11-Unterstützung aktualisiert, geht C++ C++ 03 für mindestens ein weiteres Jahr, wenn nicht zwei. Und vergessen wir nicht, dass weder GCC noch Clang volle Übereinstimmung mit C++ 11 beanspruchen. Die Zukunft ist nicht die Gegenwart, und so zu tun, als ob sie es ist, wird es nicht so machen. –

Antwort

8

Das Problem ist nicht spezifisch für std::reference_wrapper<T>, sondern eher für den Typ X selbst.

Das Problem ist, dass std::unordered_set erfordert, dass Sie Hashing und Gleichheit Funktoren für std::reference_wrapper<X> definieren. Sie können den Hash-Funktor als zweiten Vorlagenparameter übergeben.

Zum Beispiel das funktionieren würde:

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

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

und dann

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

Eine weitere Möglichkeit, eine Spezialisierung für std::hash<X> zu machen ist:

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

Hiermit können Sie ausdrücklich vermeiden Angeben des zweiten Vorlagenarguments:

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

In Bezug auf die Gleichstellung Vergleich, können Sie dieses Problem beheben, indem sie einen Gleichheitsoperator für die Klasse bietet X:

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

Andernfalls können Sie Ihren eigenen Funktor definieren und als drittes Vorlage Argument übergeben.

+0

Wäre nicht die Spezialisierung von 'std :: hash' etwas einfacher? – Griwes

+0

Es wäre, wenn Sie bereit sind, Sachen in den Namespace 'std' zu legen. – juanchopanza

+0

Ich denke nicht, dass es als "putting stuff in' std "qualifiziert werden sollte, da es sich nur um eine Spezialisierung handelt ... – Griwes

Verwandte Themen