英文:
Looking for example usages of boost::iterator_facade
问题
我有现有的代码,其中包含一些 facade_iterators,我想要从(C)Python中与它们进行接口交互。从Python的角度来看,我的想法如下:
- 初始化迭代器
- 连续调用 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:
- Initialize the iterator
- 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 <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()?
EDIT: I tried replacing the three last lines in main() by
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;
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<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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论