【问题标题】:Implement a C++ which supports 2 level looks with keys of any type使用任何类型的键实现支持 2 级外观的 C++
【发布时间】:2013-05-01 15:36:34
【问题描述】:

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

数据:

键 - 字符串

子键 - 字符串/双精度

值 - 字符串/双精度

键和子键共同唯一标识行。

例如:

[ "key", "subkey", "value" ]

[ "cse", "a", 100 ]

[ "cse", "b", 120 ]

[ "cse", 100, 10 ]

操作:

1) 给定一个键和返回值

2) 给定一个键返回一个[ "subkey", "value" ]的数组

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

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

第二级映射的键是新的包装类,值也是一个新的包装类。

这种方法对吗?还是有更好的方法来做到这一点?

【问题讨论】:

    标签: c++ database boost stdmap


    【解决方案1】:

    我使用 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;
    }
    

    【讨论】:

      【解决方案2】:

      以下每个键会浪费一点空间,但优点是简单:

      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;
      }     
      

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

      【讨论】:

      • 相当浪费空间,但可能适用于大多数情况。考虑联合或更高级别的抽象。
      • @pmr:是的,我懒得查找 C++11 非 POD 联合语法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 1970-01-01
      相关资源
      最近更新 更多