实现一个C++,它支持任何类型的键的2级外观

Implement a C++ which supports 2 level looks with keys of any type

本文关键字:类型 支持 任何 外观 2级 C++ 一个 实现      更新时间:2023-10-16

我需要实现一个C++类来支持以下

数据:

密钥字符串

子密钥-字符串/双

值-字符串/双

键&子键一起唯一地标识行。

例如:

[ "key", "subkey", "value" ]
[ "cse", "a", 100 ]
[ "cse", "b", 120 ]
[ "cse", 100, 10 ]

操作:

1( 给定一个键&返回值

2( 给定一个密钥返回一个[ "subkey", "value" ] 数组

我面临的问题是,子键和值既可以是双精度的,也可以是字符串。解决这个问题的一种方法是拥有一个包装器类,该类能够存储double和string类型。

第一级映射将有一个字符串作为键,值将是一个映射。

第二级映射将具有作为新包装器类的键,并且value也是一个新的包装器类。

这种方法正确吗?或者有更好的方法吗?

我用Boost.Variant和C++11 unordered_map破解了一个解决方案。该代码是一个非常好的例子,适用于C++11。

你需要特别注意这两个散列的组合在std::hash<key>::operator()的专业化中,它可以具有强烈影响哈希的质量。为了更好地实施看看boost::hash_combine,遗憾的是它还没有标准化。

一般来说,代码的作用是:定义一个特殊的键类型EqualityComparable和Hashable,然后在std::unordered_map。你可以用Boost和no来构建所有这些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;
}

以下每个键浪费了一点空间,但具有简单的优点:

struct Key
{
    Key(string primary, string subkey)
        : primary(primary)
        , is_double(false)
        , string_subkey(subkey)
    {}
    Key(string primary, double subkey)
        : primary(primary)
        , is_double(true)
        , double_subkey(subkey)
    {}
    string primary;
    bool is_double;
    double double_subkey;
    string string_subkey;
}     

您需要实现适当的比较操作和/或散列函数。