通过BOOST_FOREACH使我的C ++类可迭代

时间:2009-10-20 22:31:38

标签: c++ design-patterns iterator

我有一个类,我想要公开一个结构列表(它只包含一些整数)。 我不希望外部修改这些数据,只是迭代它并读取它们 例如:

struct TestData
{
  int x;
  int y;
  // other data as well
}

class IterableTest
{
  public:
    // expose TestData here
};

现在在我的代码中我想像我这样使用我的类:

IterableTest test;
BOOST_FOREACH(const TestData& data, test.data())
{
  // do something with data
}

我已经阅读了有关成员空间的这篇文章http://accu.org/index.php/journals/1527。 但是,我不想(或不能)将所有TestData保存在内部向量中。 这是因为类本身并不拥有存储,即实际上没有可以由类直接访问的底层容器。但是,类本身可以查询外部组件以获取next,previous或iith元素。

所以基本上我希望我的班级表现得好像它有一个集合,但事实上它没有一个。 有什么想法吗?

3 个答案:

答案 0 :(得分:5)

听起来你必须编写自己的迭代器。

Boost.Iterator库有许多有用的模板。我曾经多次使用过他们的Iterator Facade基类,使用它来定义自己的迭代器很方便。

但即使没有它,迭代器也不是火箭科学。他们只需暴露正确的运算符和typedef。在你的情况下,它们只是在它们增加时必须调用的查询函数的包装器。

一旦定义了迭代器类,您只需要向您的班级添加begin()end()成员函数。

听起来基本的想法是在迭代器递增时调用查询函数,以获得下一个值。 然后取消引用应返回从上次查询调用中检索到的值。

对于某些语义,看看标准库stream_iterator可能会有所帮助,因为它们还必须解决一些可疑问题“我们实际上没有容器,我们不能创建指向除当前流位置以外的任何位置的迭代器“问题。

例如,假设您需要调用query()函数,当您到达序列的末尾时返回NULL,创建“end-iterator”将会非常棘手。但实际上,您需要的只是定义相等性,以便“迭代器相等,如果它们都将NULL存储为缓存值”。所以用NULL初始化“end”迭代器。

查找输入迭代器所需的语义,或者如果您正在阅读Boost.Iterator的文档,可能有助于查找单通道迭代器。您可能无法创建多通迭代器。因此,请准确查看单遍迭代器所需的行为,并坚持下去。

答案 1 :(得分:0)

  

如果您的集合类型提供标准容器界面,则无需执行任何操作即可使BOOST_FOREACH与您的类型一起使用。换句话说,如果您的类型包含iteratorconst_iterator嵌套的typedef,以及begin()end()成员函数,BOOST_FOREACH已经知道如何迭代您的类型。无需采取进一步行动。

http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/boost_foreach/extending_boost_foreach.html

答案 2 :(得分:0)

来自Boost FOR_EACH文档页面:

  

BOOST_FOREACH迭代序列。但究竟什么才能成为序列呢?由于BOOST_FOREACH是在Boost.Range之上构建的,因此它自动支持Boost.Range识别为序列的那些类型。具体来说,BOOST_FOREACH适用于满足单通道范围概念的类型。例如,我们可以使用BOOST_FOREACH: