通过BOOST_FOREACH使我的C ++类可以迭代 [英] Make my C++ Class iterable via BOOST_FOREACH

查看:107
本文介绍了通过BOOST_FOREACH使我的C ++类可以迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  struct TestData 
{
int x;
int y;
//其他数据以及
}

class IterableTest
{
public:
//在此处显示TestData
} ;

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

  IterableTest测试; 
BOOST_FOREACH(const TestData& data,test.data())
{
//执行数据
}
pre>

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



所以基本上我希望我的类的行为就好像它有一个集合,但实际上没有一个。
任何想法?

解决方案

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



Boost.Iterator库有一些有用的模板。我使用了他们的Iterator Facade基类几次,使用它来定义自己的迭代器是很好和容易的。



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



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



听起来,当迭代器递增时,基本思想就是要调用查询函数,以获取下一个值。
然后,dereference应该返回从上次查询调用中检索的值。



可能有助于查看标准库 stream_iterator s的某些语义,因为他们也必须解决一些琐事我们真的没有一个容器,我们不能创建指向除当前流位置以外任何地方的迭代器



例如,假设您需要调用 query()函数,返回NULL,已经到了序列的末尾,创建一个最终迭代器将是棘手的。但是真的,你需要的是定义相等性,以便如果它们都将NULL作为它们的缓存值存储,迭代器是相等的。所以初始化NULL的end迭代器。



它可能有助于查询输入迭代器所需的语义,或者如果您正在阅读Boost.Iterator的文档,专用于单遍迭代器。您可能无法创建multipass迭代器。所以请查看单遍迭代器需要什么样的行为,并坚持下去。


I have a class which I want to expose a list of structs (which just contain some integers). I don't want the outside to modify these data, just iterate over it and read them Example:

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

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

now in my code I want to use my class like this:

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

I've already read this article http://accu.org/index.php/journals/1527 about memberspaces. However, I don't want to (or can't) save all TestData in an internal vector or something. This is because the class itself doesn't own the storage, i.e. there is actually no underlying container which can be accessed directly by the class. The class itself can query an external component to get the next, previous or ith element, though.

So basically I want my class to behave as if it had a collection, but in fact it doesn't have one. Any ideas?

解决方案

It sounds like you have to write your own iterators.

The Boost.Iterator library has a number of helpful templates. I've used their Iterator Facade base class a couple of times, and it's nice and easy to define your own iterators using it.

But even without it, iterators aren't rocket science. They just have to expose the right operators and typedefs. In your case, they're just going to be wrappers around the query function they have to call when they're incremented.

Once you have defined an iterator class, you just have to add begin() and end() member functions to your class.

It sounds like the basic idea is going to have to be to call your query function when the iterator is incremented, to get the next value. And dereference should then return the value retrieved from the last query call.

It may help to take a look at the standard library stream_iterators for some of the semantics, since they also have to work around some fishy "we don't really have a container, and we can't create iterators pointing anywhere other than at the current stream position" issues.

For example, assuming you need to call a query() function which returns NULL when you've reached the end of the sequence, creating an "end-iterator" is going to be tricky. But really, all you need is to define equality so that "iterators are equal if they both store NULL as their cached value". So initialize the "end" iterator with NULL.

It may help to look up the required semantics for input iterators, or if you're reading the documentation for Boost.Iterator, for single-pass iterators specifically. You probably won't be able to create multipass iterators. So look up exactly what behavior is required for a single-pass iterator, and stick to that.

这篇关于通过BOOST_FOREACH使我的C ++类可以迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆