std::chrono::duration的std::hash

4

我正在尝试使用std :: chrono :: duration对一组对象进行关键字排序。 这将无法编译:

#include <unordered_map>
#include <chrono>

class Foo final
{
public:

    Foo() {}

    int y;
};


int main(void)
{
    auto map = std::unordered_map<std::chrono::duration<int, std::milli>, Foo>();

    map[std::chrono::duration<int, std::milli>(5)].y = 0;

    return 0;
}

我猜问题在于没有为std::chrono::duration实现std::hash?如果是这样,有没有一种方法可以避免使用易于破解的count()作为键值?

/usr/include/c++/4.9/bits/hashtable_policy.h: 在 'struct std::__detail::__is_noexcept_hash >, std::hash > > >' 的实例化中:


2
float 不可哈希,这就是问题所在。 - Sam Varshavchik
2
哈希计数()有什么问题? - Sam Varshavchik
1
那么?你的映射键是毫秒持续时间,因此所有的count()都将是毫秒。 - Sam Varshavchik
1
你需要支持多长时间?如果不是太长,你可以使用单个细粒度类型来表示地图,然后将其他时间段转换为该类型。 - NathanOliver
@Robinson 我已经解决了,static_cast就足够了:“在浮点数时间间隔或者源时间间隔恰好可以被目标时间间隔整除的整数时间间隔之间进行转换(例如从小时到分钟),可以隐式地执行,不需要使用duration_cast。”http://en.cppreference.com/w/cpp/chrono/duration/duration_cast notes - R2RT
显示剩余5条评论
1个回答

3

好的,您可以在自己的 std::hash 实现下隐藏 count,具体参考http://en.cppreference.com/w/cpp/utility/hash

#include <unordered_map>
#include <chrono>

class Foo final
{
public:

    Foo() {}

    int y;
};

using namespace std::chrono_literals;

// custom specialization of std::hash can be injected in namespace std
namespace std
{
    template<typename _rep, typename ratio>
    struct hash<std::chrono::duration<_rep, ratio>>
    {
        typedef std::chrono::duration<_rep, ratio> argument_type;
        typedef std::size_t result_type;
        result_type operator()(argument_type const& s) const
        {
            return std::hash<_rep>{}(s.count());
        }
    };
}


int main(void)
{
    auto map = std::unordered_map<std::chrono::duration<float, std::milli>, Foo>();

    map[std::chrono::duration<float, std::milli>(5)].y = 12;
    std::cout << map[5ms].y; // thanks to std::chrono_literals

    return 0;
}

如果您担心将不同的比率传递到地图中,您也可以使用static_cast转换为一些最小时间精度,例如std::micro

return std::hash<_rep>{}( static_cast<std::chrono::duration<_rep, std::micro>>(s).count()); 

@Robinson,我刚刚编辑了我的答案,static_cast就足够了。 - R2RT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接