Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to allow range-for loop on my class? [duplicate]

I have a class like this:

class Foo {
private:
    int a,b,c,d;
    char bar;
    double m,n
public:
    //constructors here
};

I wanna allow range-for loop on my class, e.g.

Foo foo {/*...*/};
for(auto& f : foo) {
  //f will be a specific order such as c,b,d,(int)m,(int)bar,a,(int)n
}

How can I achieve this? I was looking at iterator but don't know what are the requirements for a range-for loop. (Please don't ask me to use array or STL type)

like image 689
SwiftMango Avatar asked Aug 19 '13 18:08

SwiftMango


2 Answers

The loop is defined to be equivalent to:

for ( auto __begin = <begin-expr>,
           __end = <end-expr>;
      __begin != __end;
      ++__begin ) {
    auto& f = *__begin;
    // loop body
}

where <begin-expr> is foo.begin(), or begin(foo) if there isn't a suitable member function, and likewise for <end-expr>. (This is a simplification of the specification in C++11 6.5.4, for this particular case where the range is a lvalue of class type).

So you need to define an iterator type that supports pre-increment ++it, dereference *it and comparison i1 != i2; and either

  • give foo public member functions begin() and end(); or
  • define non-member functions begin(foo) and end(foo), in the same namespace as foo so that they can be found by argument-dependent lookup.
like image 161
Mike Seymour Avatar answered Nov 12 '22 17:11

Mike Seymour


This seems fairly un-C++-like, and rather prone to breakage. What if the iteration order is changed (accidentally or not) during some update in the future? Clients relying on a specific order will break.

All that said if you wish to support this all you have to do is implement your own iterator and provide begin/end methods (or free functions with those names) to provide access. Then the iterator takes care of remembering which attribute it's currently looking at and provides it when dereferenced.

like image 1
Mark B Avatar answered Nov 12 '22 19:11

Mark B