我正在尝试执行以下操作:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> > map;
boost::flyweight<std::string> foo(name);
map[foo] = foo;
但编译器抱怨: “错误C2665:'boost :: hash_value':17个重载都不能转换所有参数类型”。
但我定义了以下功能:
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();
}
但它没有编译。
如何使boost unordered_map支持flyweight?
[编辑] 我让它使用以下代码:
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);
}
};
并将其作为模板参数传递给地图构造:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> , flyweight_hash > map;
在这种情况下,我不明白重载hash_value没有用。
答案 0 :(得分:7)
boost::hash
通过参数依赖查找(ADL)调用hash_value
。您正在尝试为名称空间hash_value
中的类定义boost
函数。因此,您的hash_value
函数需要进入此命名空间以及ADL才能工作。不幸的是,将函数添加到外部名称空间是相当邪恶的,应该避免。您使用自定义哈希的解决方案似乎很好。
一个小例子代码来说明:
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>...);
}
答案 1 :(得分:5)
很遗憾哈希已经被哈希过的东西。 Flyweight保持单个对象的实例,因此散列此实例的地址而不是其内容更有效。我这样做(在std
,而不在boost
,因为我正在使用C ++ 11,所以我正在扩展std::hash
,而不是boost::hash
):< / p>
namespace std
{
template <typename T>
struct hash<boost::flyweight<T, boost::flyweights::no_tracking>>
{
using value_type = boost::flyweight<T, boost::flyweights::no_tracking>;
size_t operator()(const value_type& ss) const
{
hash<const void*> hasher;
return hasher(&ss.get());
}
};
}
我已经确认这是设计的,而不是偶然的:http://lists.boost.org/boost-users/2013/03/78007.php