3

So since it was introduced I have been loving the for each in keywords to iterate STL collections.(I'm a very very big fan of syntactic sugar).

My question is how can I write a custom collection that can be iterated using these keywords?

Essentially, what APi do I need to expose for my collections to be iterable using these keywords?

I apologize if this sounds blunt, but please do not respond with "use boost", "don't write your own collections", or the like. Pursuit of knowledge, my friends. If it's not possible, hey, I can handle that.

I'd also very much so prefer not to have to inject an STL iterator into my collections.

Thanks in advance!

Anirudha
  • 32,393
  • 7
  • 68
  • 89
Will Custode
  • 4,576
  • 3
  • 26
  • 51
  • 1
    are you talking about the `std::for_each` algorithm? Or the range-based for-loop introduced in C++11? – jalf Nov 15 '12 at 17:42
  • @jalf: I'm referring to the Microsoft 'for each in' context sensitive keywords. Although the [MSDN Page](http://msdn.microsoft.com/en-us/library/vstudio/ms177202.aspx) only details C++/CLI, this works in native. – Will Custode Dec 26 '12 at 15:30

2 Answers2

10

Here is a good explanation of iterable data structures (Range-Based loops):

In order to make a data structure iterable, it must work similarly to the existing STL iterators.

  1. There must be begin and end methods that operate on that structure, either as members or as stand-alone functions, and that return iterators to the beginning and end of the structure.
  2. The iterator itself must support an operator* method, an operator != method, and an operator++ method, either as members or as stand-alone functions.

Note, in C++11 there is an integrated support for range-based loops without the use of STL, though the above conditions hold for this as well. You can read about it at the same link above.

SomeWittyUsername
  • 18,025
  • 3
  • 42
  • 85
5

It's not really clear from your quesiton whether you're talking about std::for_each defined in the <algorithm> header, or the range-based for loop introduced in C++11.

However, the answer is similar for both.

Both operate on iterators, rather than the collection itself.

So you need to

  1. define an iterator type which satisfies the requirements placed on it by the STL (the C++ standard, really). (The main things are that it must define operator++ and operator*, and a couple of other operations and typedefs)

  2. for std::for_each, there is no 2. You're done. You simply pass two such iterators to std::for_each. For the range-based for loop, you need to expose a pair of these iterators via the begin() and end() functions.

And... that's it.

The only tricky part is really creating an iterator which complies with the requirements. Boost (even though you said you didn't want to use it) has a library which aids in implementing custom iterators (Boost.Iterator). There is also the std::iterator class which is intended as a base class for custom iterator implementations. But neither of these are necessary. Both are just convenience tools to make it easier to create your own iterator.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
jalf
  • 243,077
  • 51
  • 345
  • 550