【问题标题】:How to declare STL style C++ hash map iterator?如何声明 STL 风格的 C++ 哈希映射迭代器?
【发布时间】:2020-06-09 07:32:49
【问题描述】:

这是我在 C++14 中的 HashMap 示例:

#include <string>
#include <utility>

template <class K, class V> class MyNode {
public:
  std::pair<const K, V> value;
};

template <class K, class V, class NodePtr> class MyIterator {
public:
  MyIterator(NodePtr node = nullptr) : node_(node) {}
  ~MyIterator() = default;
  MyIterator(const MyIterator &) = default;
  MyIterator &operator=(const MyIterator &) = default;

  std::pair<const K, V> &operator*() { return node_->value; }
  const std::pair<const K, V> &operator*() const { return node_->value; }
  std::pair<const K, V> *&operator->() { return &(node_->value); }
  const std::pair<const K, V> *operator->() const { return &(node_->value); }
  MyIterator<K, V, NodePtr> &operator++() { return *this; }
  MyIterator<K, V, NodePtr> operator++(int) { return *this; }

  bool operator==(const MyIterator<K, V, NodePtr> &other) {
    return node_ == other.node_;
  }
  bool operator!=(const MyIterator<K, V, NodePtr> &other) {
    return node_ != other.node_;
  }

private:
  NodePtr node_;
};

template <class K, class V> class MyHashMap {
public:
  using Iterator = MyIterator<K, V, MyNode<K, V> *>;
  using ConstIterator = MyIterator<K, V, const MyNode<K, V> *>;

  Iterator begin() { return Iterator(&node); }
  ConstIterator begin() const { return ConstIterator(&node); }
  ConstIterator cbegin() const { return ConstIterator(&node); }
  Iterator end() { return Iterator(nullptr); }
  ConstIterator end() const { return ConstIterator(nullptr); }
  ConstIterator cend() const { return ConstIterator(nullptr); }

  MyNode<K, V> node;
};

void test(const int &a) {}

int main(void) {
  MyHashMap<int, int> hm;
  for (MyHashMap<int, int>::ConstIterator i = hm.begin(); i != hm.end(); i++) {
    test(i->second);
  }
  for (MyHashMap<int, int>::ConstIterator i = hm.cbegin(); i != hm.cend();
       i++) {
    test(i->second);
  }
  return 0;
}

编译:clang++ -std=c++14 main.cpp -o main.exe

哪个给我:

main.cpp:53:43: error: no viable conversion from 'MyIterator<[2 * ...], MyNode<int, int> *>' to 'MyIterator<[2 * ...], const MyNode<int, int> *>'
  for (MyHashMap<int, int>::ConstIterator i = hm.begin(); i != hm.end(); i++) {
                                          ^   ~~~~~~~~~~
main.cpp:11:3: note: candidate constructor not viable: no known conversion from 'MyHashMap<int, int>::Iterator' (aka 'MyIterator<int, int, MyNode<int, int> *>') to 'const MyNode<int, int> *' for 1st
      argument
  MyIterator(NodePtr node = nullptr) : node_(node) {}
  ^
main.cpp:13:3: note: candidate constructor not viable: no known conversion from 'MyHashMap<int, int>::Iterator' (aka 'MyIterator<int, int, MyNode<int, int> *>') to
      'const MyIterator<int, int, const MyNode<int, int> *> &' for 1st argument
  MyIterator(const MyIterator &) = default;
  ^
main.cpp:18:49: error: non-const lvalue reference to type 'std::pair<const int, int> *' cannot bind to a temporary of type 'const std::pair<const int, int> *'
  std::pair<const K, V> *&operator->() { return &(node_->value); }
                                                ^~~~~~~~~~~~~~~
main.cpp:58:11: note: in instantiation of member function 'MyIterator<int, int, const MyNode<int, int> *>::operator->' requested here
    test(i->second);
          ^
2 errors generated.

【问题讨论】:

  • 关于你的迭代器,你可以从检查std::iterator_traits&lt;MyIterator&lt;...&gt;&gt; 包含它的所有成员类型开始(剧透,它没有;)。见std::iterator_traits

标签: c++ c++11 stl iterator


【解决方案1】:

我的 HashMap 和 Iterator 声明是否正确?

你的usings 搞错了。

您没有任何Node&lt;K, const V&gt;s 可以指向。

要符合Container,你应该拼写它iteratorconst_iterator,并提供另一个usings

您要么需要专门化std::iterator_traits,要么提供它需要的定义。

template <class K, class V>
class MyHashMap {
public:
  using iterator = MyIterator<K, V, Node<K, V>>;
  using const_iterator = MyIterator<K, V, const Node<K, V>> = ConstIterator;

  iterator begin();
  const_iterator begin() const;
  iterator end();
  const_iterator end() const;
};

【讨论】:

  • 为什么使用const_iterator = MyIterator&lt;K, V, const Node&lt;K, V&gt;&gt; 而不是const_iterator = MyIterator&lt;K, V, Node&lt;K, const V&gt;&gt;
  • 您没有任何Node&lt;K, const V&gt; 对象。从const Node&lt;K, V&gt; *Node&lt;K, const V&gt; * 的转换无效
  • 我认为 C++ STL 库中的 map const_iterator 使用的是const_iterator = MapIterator&lt;K, V, Node&lt;K, const V&gt;*&gt;,而不是const_iterator = MapIterator&lt;K, V, const Node&lt;K, V&gt;*&gt;
  • 我不知道你在看哪里,我的实现有typedef _Tree_const_iterator&lt;_Tree_val&lt;_Val_types&gt; &gt; const_iterator; typedef _Tree_iterator&lt;_Tree_val&lt;_Val_types&gt; &gt; iterator;
  • 你能告诉我你包含_Tree_const_iterator的源代码吗?
猜你喜欢
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 2011-04-02
  • 2011-05-11
  • 2010-12-09
  • 1970-01-01
相关资源
最近更新 更多