寻找 boost::iterator_facade 的示例用法。

huangapple go评论109阅读模式
英文:

Looking for example usages of boost::iterator_facade

问题

我有现有的代码,其中包含一些 facade_iterators,我想要从(C)Python中与它们进行接口交互。从Python的角度来看,我的想法如下:

  1. 初始化迭代器
  2. 连续调用 dereference() 和 increment()

我看到的少数代码示例只显示了 std::for_each 和 std::copy,就像官方文档中的示例一样:https://www.boost.org/doc/libs/1_65_0/libs/iterator/example/node_iterator2.cpp。但我不想一次遍历所有内容。

我尝试将函数 increment() 和 dereference() 转为公共函数,然后直接调用它们:这样可以工作。我猜想这应该使用 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:
  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:
  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;
}
// 如何在私有 increment() 和 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)时,这些函数似乎属于一个公共块。所以我感到困惑。

英文:

I have an existing code containing some facade_iterators, and I would like to interface them from (C)Python. Schematically, my idea is, from Python:

  1. Initialize the iterator
  2. Call successively dereference() and increment()

The few code examples I've seen only show std::for_each and std::copy, like here from the official doc https://www.boost.org/doc/libs/1_65_0/libs/iterator/example/node_iterator2.cpp . But I don't want to iterate over everything at once.

I've tried to turn the functions increment() and dereference() public, and then call them directly: it works. I guess this should be achieved using boost::iterator_core_access, but I cannot find how. Here is the full code:

// File test.h
#include &lt;iostream&gt;
#include &lt;boost/iterator/iterator_facade.hpp&gt;
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&amp; s) const = 0;
virtual void double_me() = 0;
void append(node_base* p) {
if (m_next) m_next-&gt;append(p);
else m_next = p;
}
private:
node_base* m_next;
};
template &lt;class T&gt;
struct node : node_base {
node(T x) : m_value(x) {}
void print(std::ostream&amp; s) const { s &lt;&lt; this-&gt;m_value; }
void double_me() { m_value += m_value; }
private:
T m_value;
};
inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, node_base const&amp; n) {
n.print(s);
return s;
}
template &lt;class Value&gt;
class node_iter : public boost::iterator_facade&lt;
node_iter&lt;Value&gt;
, Value
, boost::forward_traversal_tag&gt; {
public:
node_iter() : m_node(0) {}
explicit node_iter(Value* p) : m_node(p) {}
template &lt;class OtherValue&gt;
node_iter(node_iter&lt;OtherValue&gt; const&amp; other) : m_node(other.m_node) {}
//private: //private should start here
friend class boost::iterator_core_access;
template &lt;class&gt; friend class node_iter;
template &lt;class OtherValue&gt;
bool equal(node_iter&lt;OtherValue&gt; const&amp; other) const {
return this-&gt;m_node == other.m_node;
}
void increment() { m_node = m_node-&gt;next(); }
Value&amp; dereference() const { return *m_node; }
private: //if it&#39;s moved here, the example works
Value* m_node;
};
typedef node_iter&lt;node_base&gt; node_iterator;
typedef node_iter&lt;node_base const&gt; node_const_iterator;
// File test.cpp
#include &quot;test.h&quot;
#include &lt;iostream&gt;
#include &lt;memory&gt;
int main() {
std::unique_ptr&lt;node&lt;int&gt; &gt; nodes(new node&lt;int&gt;(42));
nodes-&gt;append(new node&lt;int&gt;(13));
auto nit = new node_iterator(nodes.get());
std::cout &lt;&lt; nit-&gt;dereference() &lt;&lt; std::endl;
nit-&gt;increment();
std::cout &lt;&lt; nit-&gt;dereference() &lt;&lt; std::endl;
return 0;
}
// How to do the same with private increment() and dereference()?

EDIT: I tried replacing the three last lines in main() by

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

But I get an error telling me that dereference() and increment() are private. However when I look in the source (boost/iterator/iterator_facade.hpp) the functions seem to belong to a public block. So I'm confused.

答案1

得分: 0

你应该使用 ++*。你可能不应该动态分配 node_iterator

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

You should be using ++ and *. You probably shouldn't be dynamically allocating node_iterator.

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

huangapple
  • 本文由 发表于 2020年1月6日 18:41:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610631.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定