我使用 Boost.Variant 和 C++11 破解了一个解决方案unordered_map
。该代码是 C++11 的一个很好的例子。
您需要特别注意在 的专业化中两个哈希的组合std::hash<key>::operator()
,它会对哈希的质量产生很大的影响。要获得更好的实现,请查看boost::hash_combine
,遗憾的是尚未标准化。
一般来说,代码的作用是:定义一个特殊的键类型,即 EqualityComparable 和 Hashable,然后在
std::unordered_map
. 您可以仅使用 Boost 构建所有这些,而根本不需要 C++11。如果您既没有 Boost 也没有 C++11,那么您就处于困境中。没有对此进行真正的测试。
#include <boost/variant.hpp>
#include <string>
#include <functional>
#include <unordered_map>
#include <iostream>
struct key {
std::string primary;
boost::variant<std::string, double> secondary;
friend bool operator==(const key& x, const key& y)
{ return x.primary == y.primary && x.secondary == y.secondary; }
};
namespace std {
template<>
struct hash<key> {
std::size_t operator()(const key& k) const
{
std::size_t first = std::hash<std::string>()(k.primary);
std::size_t second;
// check for the more likely case first
if(const std::string* s = boost::get<std::string>(&(k.secondary))) {
second = std::hash<std::string>()(*s);
} else {
const double* d = boost::get<double>(&(k.secondary));
second = std::hash<double>()(*d);
}
return first ^ ( second << 1 ); // not so fancy hash_combine
}
};
} // std
int main()
{
typedef std::unordered_map<key, boost::variant<std::string, double>> MyMap;
MyMap m = {
{{"foo", "bar"}, "foobar"},
{{"foo", 23.0}, "foo23"},
{{"nothing", 23.0}, 23.0}
};
std::cout << m[{"foo", "bar"}] << std::endl;
std::cout << m[{"foo", 23.0}] << std::endl;
std::cout << m[{"nothing", 23.0}] << std::endl;
return 0;
}