Ищем пример использования boost :: iterator_facade - PullRequest
1 голос
/ 06 января 2020

У меня есть существующий код, содержащий несколько фасадных_итераторов, и я хотел бы связать их с (C) Python. Схематически моя идея заключается в том, чтобы Python:

  1. Инициализировать итератор
  2. Вызовите последовательно dereference () и increment ()

Несколько кодов примеры, которые я видел, показывают только std :: for_each и std :: copy, как здесь, из официального do c https://www.boost.org/doc/libs/1_65_0/libs/iterator/example/node_iterator2.cpp. Но я не хочу перебирать все сразу.

Я попытался включить функции increment () и dereference () publi c, а затем вызвать их напрямую: это работает. Я думаю, что это должно быть достигнуто с помощью boost :: iterator_core_access, но я не могу найти, как. Вот полный код:

// File test.h
#include <iostream>
#include <boost/iterator/iterator_facade.hpp>

struct node_base {
  node_base() : m_next(0) {}
  virtual ~node_base() { delete m_next; }
  node_base* next() const { return m_next; }
  virtual void print(std::ostream& s) const = 0;
  virtual void double_me() = 0;
  void append(node_base* p) {
    if (m_next) m_next->append(p);
    else m_next = p;
  }
 private:
  node_base* m_next;
};

template <class T>
struct node : node_base {
  node(T x) : m_value(x) {}
  void print(std::ostream& s) const { s << this->m_value; }
  void double_me() { m_value += m_value; }
 private:
  T m_value;
};

inline std::ostream& operator<<(std::ostream& s, node_base const& n) {
  n.print(s);
  return s;
}

template <class Value>
class node_iter : public boost::iterator_facade<
        node_iter<Value>
      , Value
      , boost::forward_traversal_tag> {
 public:
  node_iter() : m_node(0) {}
  explicit node_iter(Value* p) : m_node(p) {}
  template <class OtherValue>
  node_iter(node_iter<OtherValue> const& other) : m_node(other.m_node) {}
 //private: //private should start here
  friend class boost::iterator_core_access;
  template <class> friend class node_iter;
  template <class OtherValue>
  bool equal(node_iter<OtherValue> const& other) const {
    return this->m_node == other.m_node;
  }
  void increment() { m_node = m_node->next(); }
  Value& dereference() const { return *m_node; }
 private: //if it's moved here, the example works
  Value* m_node;
};
typedef node_iter<node_base> node_iterator;
typedef node_iter<node_base const> node_const_iterator;

// File test.cpp
#include "test.h"
#include <iostream>
#include <memory>

int main() {
  std::unique_ptr<node<int> > nodes(new node<int>(42));
  nodes->append(new node<int>(13));
  auto nit = new node_iterator(nodes.get());
  std::cout << nit->dereference() << std::endl;
  nit->increment();
  std::cout << nit->dereference() << std::endl;
  return 0;
}
// How to do the same with private increment() and dereference()?

РЕДАКТИРОВАТЬ: я попытался заменить три последние строки в main () на

  std::cout << boost::iterator_core_access::dereference(*nit) << std::endl;
  boost::iterator_core_access::increment(*nit);
  std::cout << boost::iterator_core_access::dereference(*nit) << std::endl;

Но я получаю сообщение об ошибке, сообщающее, что dereference () и increment () являются частными. Однако, когда я смотрю в исходном коде (boost / iterator / iterator_facade.hpp), кажется, что функции принадлежат к блоку publi c. Так что я в замешательстве.

1 Ответ

0 голосов
/ 06 января 2020

Вы должны использовать ++ и *. Вы, вероятно, не должны динамически распределять node_iterator.

int main() {
  std::unique_ptr<node<int> > nodes = std::make_unique(42);
  nodes->append(std::make_unique(13));
  node_iterator nit(nodes.get());
  std::cout << *nit << std::endl;
  ++nit;
  std::cout << *nit << std::endl;
  return 0;
}
...