Fre*_*rik 10 c++ boost unordered-map flyweight-pattern
我正在尝试执行以下操作:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> > map;
boost::flyweight<std::string> foo(name);
map[foo] = foo;
Run Code Online (Sandbox Code Playgroud)
但编译器抱怨:"错误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();
}
Run Code Online (Sandbox Code Playgroud)
但它没有编译.
我需要做些什么才能使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);
}
};
Run Code Online (Sandbox Code Playgroud)
并将其作为模板参数传递给地图的构造:
boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> , flyweight_hash > map;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我不明白重载hash_value没有工作的方式.
boost::hashhash_value通过参数依赖查找(ADL)调用.您正在尝试为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>...);
}
Run Code Online (Sandbox Code Playgroud)
对已经被哈希过的东西进行哈希处理是一种遗憾.Flyweight保持单个对象的实例,因此散列此实例的地址而不是其内容更有效.我这样做(in std,not in boost,因为我正在使用C++ 11,所以我正在扩展std::hash,而不是boost::hash):
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());
}
};
}
Run Code Online (Sandbox Code Playgroud)
我已经确认这是设计的,而不是偶然的:http://lists.boost.org/boost-users/2013/03/78007.php
| 归档时间: |
|
| 查看次数: |
1982 次 |
| 最近记录: |