Is unordered_set <reference_wrapper <Ty>> valid?
Is this valid C ++ (given the latest standard)? I get compilation errors close to the top of the clang / libC ++ tree on Ubuntu 12.04. If it is valid, I will send a list of clang-dev to error messages, etc.
#include <functional> #include <unordered_set> struct X { int i; }; void f () { std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; // Do stuff with setOfReferencesToX } ** Aside, Iām tired of qualifying that the question / answer refers to the latest standard. Can the C ++ community as a whole, please start qualifying things specific to the old standard only? A newer standard has been around for about a year.
The problem does not apply to std::reference_wrapper<T> , but to type X
The problem is that std :: unordered_set requires you to define hash and equality functions for std::reference_wrapper<X> . You can pass the hash functor as the second parameter of the template.
For example, this will work:
#include <functional> // for std::hash<int> struct HashX { size_t operator()(const X& x) const { return std::hash<int>()(xi); } }; and then
std::unordered_set<std::reference_wrapper<X>, HashX> setOfReferencesToX; Another option is to do specialization for std::hash<X> :
namespace std { template <> struct hash<X> { size_t operator()(const X& x) const { return std::hash<int>()(xi); } }; } This avoids explicitly specifying the argument of the 2nd pattern:
std::unordered_set<std::reference_wrapper<X>> setOfReferencesToX; Regarding equality comparison, you can fix this by providing an equality operator for class X :
struct X { bool operator==(const X& rhs) const { return i == rhs.i; } int i; }; Otherwise, you can define your own functor and pass it as the third argument to the template.