2009-10-20 37 views
11

我有一个类,我想公开一个结构体列表(它只包含一些整数)。 我不希望外界修改这些数据,只是遍历并阅读他们 例子:让我的C++类通过BOOST_FOREACH迭代

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保存在内部向量中或其他东西。 这是因为类本身并不拥有存储空间,即实际上没有可以被类直接访问的底层容器。不过,该类本身可以查询外部组件以获取下一个,前一个或第i个元素。

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

+4

你不需要提供返回合​​适迭代器的begin/end函数吗? – jalf 2009-10-20 22:34:42

+0

是的,但我没有一个底层容器可以提供给我这些迭代器 – newgre 2009-10-20 22:37:01

+0

所以你自己写。 :) Boost.Iterator库应该让你启动并运行相当快。 – jalf 2009-10-20 22:37:56

回答

5

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

Boost.Iterator库有许多有用的模板。我几次使用过他们的Iterator Facade基类,并且使用它定义自己的迭代器很好,很容易。

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

一旦您定义了一个迭代器类,您只需将begin()end()成员函数添加到您的类中。

这听起来像基本的想法将不得不调整你的查询函数,当​​迭代器增加,以获得下一个值。 然后解引用应返回从最后一个查询调用中检索的值。

这可能有助于查看标准库stream_iterator的某些语义,因为它们还必须解决一些鱼腥味“我们没有真正的容器,而且我们也不能创建迭代器指向任何地方,除了目前的河流位置“问题。

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

它可能有助于查找输入迭代器所需的语义,或者如果您正在阅读Boost.Iterator的文档,专门针对单遍迭代器。您可能无法创建多通道迭代器。因此,请仔细查看单通迭代器需要的行为,并坚持这一点。

+0

因为我是个好人:Input Iterator概念>> http://www.sgi.com/tech/stl/InputIterator.html – 2009-10-21 09:20:52

0

如果您的收集类型提供标准容器界面,则不需要执行任何操作使BOOST_FOREACH适用于您的类型。换句话说,如果您的类型具有iteratorconst_iterator嵌套typedefs,并且begin()end()成员函数,BOOST_FOREACH已知道如何迭代您的类型。不需要采取进一步行动。

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

+0

我知道这件事,但我从哪里得到这些迭代器?没有可以使用迭代器的底层容器 – newgre 2009-10-20 22:39:21

0

从升压的for_each文档页面:

在序列BOOST_FOREACH迭代。但是,什么样的资格作为一个序列呢?由于BOOST_FOREACH构建在Boost.Range之上,因此它自动支持Boost.Range认为是序列的那些类型。具体而言,BOOST_FOREACH适用于满足单通范围概念的类型。例如,我们可以使用BOOST_FOREACH: