【问题标题】:How implement a custom std collection in C++?如何在 C++ 中实现自定义标准集合?
【发布时间】:2023-03-31 13:00:03
【问题描述】:

我想以 std 样式实现自定义集合数据结构。这个网站上已经有一个similar question,但是这个人明确询问不使用任何给定的标准功能。

实现应该与标准库的其余部分兼容并提供相同的接口,例如迭代器和类型特征。我应该从哪个基类继承,我的类必须实现什么?

为了提供有关实际数据结构的信息,它是内存中的hash map which values are stored continuously。在内部,我将使用两个std::vectors 和一个std::unordered_map

【问题讨论】:

标签: c++ collections interface stl iterator


【解决方案1】:

我应该从哪个基类继承

没有。标准容器不是多态的;它们的接口要求是根据必须支持的表达式来非正式指定的。 (将来,它们可能会被正式指定为“概念”;但这还不是语言的一部分。)

我的班级必须实现什么?

参见 C++ 标准的 [container.requirements] 部分(当前为 C++11 的 23.2 部分);特别是指定各种容器类型必须支持的操作的表。作为哈希映射,它应该支持“无序关联容器”的要求。

【讨论】:

    【解决方案2】:

    从类似这样的界面开始:

    template <
        typename Key,
        typename T,
        class Hash = hash<Key>,
        class Pred = equal_to<Key>,
        class AllocH = allocator< pair<const Key,T> >,  // unordered_map allocator
        class AllocV = allocator<T> > // vector allocator
    class hash_map {
    public:
      typedef std::pair<Key, T> value_type;
    
    private:
      using first_index = std::vector<T>; // C++11 typedef substitute syntax
      using second_index = std::unordered_map<Key, T>;
    
    public:          
      using first_index_iterator = typename first_index::iterator;
      using second_index_iterator = typename second_index::iterator;      
      //defaults
      using iterator = first_index_iterator;
      using const_iterator = first_index_const_iterator;
    
      iterator begin();
      const_iterator begin() const;
    
      iterator end();
      const_iterator end() const;
    
      bool empty() const;
    
      iterator find(const Key&);
      const_iterator find(const Key&) const;
    
      std::pair<iterator, bool> insert(const value_type&);
      void erase(iterator);  
      void clear();    
    };
    

    您不应该将您的集合添加到 std 命名空间,但是如果您仍然继续,我强烈建议您在发布库头时使用命名空间版本控制:

    // hash_map.hpp
    namespace std 
    {
      namespace ex_v1  // my std namespace extensions v1
      {
          template <...> class hash_map { ... }    
      }
    
      using namespace ex_v1;
    }
    

    此外,考虑 C++11 的新 内联 版本控制功能:

    【讨论】:

    • 非常感谢您的回答。我实际上需要两个迭代器。一个只包含值并简单地遍历向量,另一个包含键和值,通过在查找表中查找键。是否有提供两个迭代器的首选方式?我可以考虑将布尔标志添加到 begin()end() 或以不同的名称实现这些函数的替代方案。
    • @danijar 您可能希望将可用于访问您的容器的索引的概念形式化,迭代器只是派生的。无论如何,我已经用一个小样本更新了答案,说明它在最简单的情况下的样子,其中索引只是底层容器的直接映射。
    猜你喜欢
    • 2017-06-30
    • 1970-01-01
    • 2011-06-05
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多