我有一个类,我想要公开一个结构列表(它只包含一些整数)。 我不希望外部修改这些数据,只是迭代它并读取它们 例如:
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元素。
所以基本上我希望我的班级表现得好像它有一个集合,但事实上它没有一个。 有什么想法吗?
答案 0 :(得分:5)
听起来你必须编写自己的迭代器。
Boost.Iterator库有许多有用的模板。我曾经多次使用过他们的Iterator Facade基类,使用它来定义自己的迭代器很方便。
但即使没有它,迭代器也不是火箭科学。他们只需暴露正确的运算符和typedef。在你的情况下,它们只是在它们增加时必须调用的查询函数的包装器。
一旦定义了迭代器类,您只需要向您的班级添加begin()
和end()
成员函数。
听起来基本的想法是在迭代器递增时调用查询函数,以获得下一个值。 然后取消引用应返回从上次查询调用中检索到的值。
对于某些语义,看看标准库stream_iterator
可能会有所帮助,因为它们还必须解决一些可疑问题“我们实际上没有容器,我们不能创建指向除当前流位置以外的任何位置的迭代器“问题。
例如,假设您需要调用query()
函数,当您到达序列的末尾时返回NULL,创建“end-iterator”将会非常棘手。但实际上,您需要的只是定义相等性,以便“迭代器相等,如果它们都将NULL存储为缓存值”。所以用NULL初始化“end”迭代器。
查找输入迭代器所需的语义,或者如果您正在阅读Boost.Iterator的文档,可能有助于查找单通道迭代器。您可能无法创建多通迭代器。因此,请准确查看单遍迭代器所需的行为,并坚持下去。
答案 1 :(得分:0)
如果您的集合类型提供标准容器界面,则无需执行任何操作即可使
BOOST_FOREACH
与您的类型一起使用。换句话说,如果您的类型包含iterator
和const_iterator
嵌套的typedef,以及begin()
和end()
成员函数,BOOST_FOREACH
已经知道如何迭代您的类型。无需采取进一步行动。
答案 2 :(得分:0)
来自Boost FOR_EACH文档页面:
BOOST_FOREACH迭代序列。但究竟什么才能成为序列呢?由于BOOST_FOREACH是在Boost.Range之上构建的,因此它自动支持Boost.Range识别为序列的那些类型。具体来说,BOOST_FOREACH适用于满足单通道范围概念的类型。例如,我们可以使用BOOST_FOREACH: