I am trying to do the following:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> > map;
boost::flyweight<std::string> foo(name);
map[foo] = foo;
But the compiler complains: "error C2665: 'boost::hash_value' : none of the 17 overloads could convert all the argument types".
But I have defined the following function:
std::size_t hash_value(const boost::flyweight<std::string> & b)
{
boost::hash<std::string> hasher;
const std::string & str = b.get();
return hasher(str);
}
bool operator==(const boost::flyweight<std::string>& f, const boost::flyweight<std::string> & second)
{
return f.get() == second.get();
}
But it doesn´t compile.
What do I need to do to make boost unordered_map to support flyweight?
[EDIT] I got it to work with the following code:
struct flyweight_hash
{
std::size_t operator()(const boost::flyweight<std::string> &elm) const
{
boost::hash<std::string> hasher;
const std::string & str = elm.get();
return hasher(str);
}
};
and passed it as a template parameter to the construction of the map:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> , flyweight_hash > map;
In this case I don´t understand way overloading hash_value didn´t worked.
boost::hash
calls hash_value
through argument dependent lookup (ADL). You are trying to define a hash_value
function for a class in namespace boost
. Hence your hash_value
function would need to go into this namespace as well for ADL to work. Unfortunately, adding functions to a foreign namespace is rather evil and should be avoided. Your solution of using a custom hasher seems fine.
A little example code to illustrate:
namespace boost {
// somewhere in boost
template<typename T>
std::size_t hash(const T& t) {
// call using ADL
// e.g. if called with object of class type foo::bar this will
// pick up foo::hash_value despite the lack of namespace
// qualification
return hash_value(t);
}
}
// your hash_value (presumably in the global namespace)
// not picked up by above call
std::size_t hash_value(boost::flyweight<T>...);
namespace boost {
// this would be picked up but is slightly evil
std::size_t hash_value(boost::flyweight<T>...);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With