2

I am going to implement a list class and want to iterate through the whole list.

Is this proper C++ to do something like:

for (auto i : *this)

If not, what would be the proper syntax for a range-based for loop?

StarckOverflar
  • 1,577
  • 2
  • 10
  • 13
  • 4
    It can be made to work, if that's what you are asking. – Igor Tandetnik Dec 18 '16 at 02:33
  • ... it's very strange. Why do you want do this. – Stargateur Dec 18 '16 at 02:38
  • @IgorTandetnik Yes, it's basically what I'm asking. Will this syntax work? – StarckOverflar Dec 18 '16 at 02:54
  • @Stargateur I just need to loop across all the elements in this particular object of the class – StarckOverflar Dec 18 '16 at 02:55
  • 1
    As [documentation suggests](http://en.cppreference.com/w/cpp/language/range-for) range-for is just a syntactic sugar internally evaluated as an ordinary iterator-based loop. So you need to implement an iterator for the set of elements you need to iterate. – user3159253 Dec 18 '16 at 03:02
  • 1
    If you need to iterate over members of the object instance, you need to look at various introspection/reflection techniques available for C++. Check [this SO QA](http://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application) for more information – user3159253 Dec 18 '16 at 03:05

3 Answers3

0

Your list class needs to have suitable begin() and end() member functions, or else there must be suitable free functions with these names. See here for example.

There is nothing special about this. If your list class is L and l has type L then you can do:

for (auto i : l)
James Hirschorn
  • 7,032
  • 5
  • 45
  • 53
0

Example

list<T> l{....};

Post C++11

for(auto & elem : l)
    cout<<elem;

Usual Way

for(list<T>::iterator it = l.begin();it!=l.end();++it)
    cout<<*it;
instance
  • 1,366
  • 15
  • 23
0

As per the documentation, the range-for loop is defined as it follows (until C++17):

{
    auto && __range = range_expression ; 
    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
    }
}

Therefore you have just to define a couple of functions, that are begin and end. They can be either member functions or accessible via ADL.
This way you'll be able to use your type in a range-for loop, either from within the class itself (using *this) or from anywhere else (by using a named variable).


It follows a minimal, working example:

#include<list>
#include<iostream>

struct my_list {
    using iterator = std::list<int>::iterator;

    friend iterator begin(my_list &);
    friend iterator end(my_list &);

    void f() {
        for(auto v: *this) {
            std::cout << v << std::endl;
        }
    }

private:
    std::list<int> data{ 0, 1, 2 };
};

my_list::iterator begin(my_list &l) {
    return l.data.begin();
}

my_list::iterator end(my_list &l) {
    return l.data.end();
}

int main() {
    my_list l{};
    l.f();

    for(auto v: l) {
        std::cout << v << std::endl;
    }
}
skypjack
  • 49,335
  • 19
  • 95
  • 187