Reputation: 10132
I'm trying to key a set of objects on a std::chrono::duration. This will not compile:
#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;
}
/usr/include/c++/4.9/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::__is_noexcept_hash >, std::hash > > >':
I'm guessing the problem here is there's no std::hash implementation for std::chrono::duration? If not, is there a way of doing this without resorting to keying on the eminently breakable count()?
Upvotes: 4
Views: 1711
Reputation: 2146
Well, you could hide count
under your own std::hash implementation 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;
}
If you are afraid of passing different ratios into your map you could also use static_cast
into some minimal time precision, eg. std::micro
:
return std::hash<_rep>{}( static_cast<std::chrono::duration<_rep, std::micro>>(s).count());
Upvotes: 3