如何使boost unordered_map支持flyweight <string>

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没有工作的方式.

pmr*_*pmr 7

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)


aki*_*kim 5

对已经被哈希过的东西进行哈希处理是一种遗憾.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