版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ssss1223ss/article/details/89281139
std::unordered_map
是c++11引入的关联容器,其HashMap
特性和std::map
的区别且不讨论,我们先看它的find
和count
方法:
iterator find( const Key& key );(1)
iterator find( const Key& key, size_t hash );(1) (C++20 起)
const_iterator find( const Key& key ) const;(2)
const_iterator find( const Key& key, size_t hash ) const;(2) (C++20 起)
template< class K > iterator find( const K& x );(3) (C++20 起)
template< class K > iterator find( const K& x, size_t hash );(3) (C++20 起)
template< class K > const_iterator find( const K& x ) const;(4) (C++20 起)
template< class K > const_iterator find( const K& x, size_t hash ) const; (4) (C++20 起)
size_type count( const Key& key ) const;(1) (C++11 起)
size_type count( const Key& key, std::size_t hash ) const;(1) (C++20 起)
template< class K >
size_type count( const K& x ) const;(2) (C++20 起)
template< class K >
size_type count( const K& x, std::size_t hash ) const;(2) (C++20 起)
问题是:c++20之前如何使用其他类型的Key操作std::unordered_map
呢?
我的方案是: 定义一个包含所有Key类型的tagged union UnionKey
来作为std::unordered_map
的Key,UnionKey
要特化std::hash
和std::equal_to
。 这里提供一个c++17 variant的实现版本。
#include <cassert>
#include <string_view>
#include <string>
#include <unordered_map>
#include <variant>
namespace std
{
template<typename ... Ts>
struct equal_to<std::variant<Ts...>>
{
bool operator()(const std::variant<Ts...>& rhs, const std::variant<Ts...>& lhs) const
{
return std::visit([](auto && rhs, auto && lhs) { return rhs == lhs; }, rhs, lhs);
}
};
}
template<typename V, typename ... K>
using Map = std::unordered_map<std::variant<K...>, V>;
int main()
{
Map<int, std::string, std::string_view> m;
using namespace std::string_view_literals;
using namespace std::string_literals;
m.insert({ "123"s, 123 });
m.insert({ "abc"sv, 456 });
m["123"sv] = 234;
auto it = m.find("123"sv);
assert(m.end() != it && it->second == 234);
assert(1 == m.count("abc"s));
}