0

I'm wondering which iterator the range based for loop uses for classes like std::map; I'm assuming by default it uses std::map::iterator instead of say std::map::reverse_iterator. Is this correct, and is there a way that I can tell it to instantiate the iterator that I prefer, or do I just need to use a traditional for loop at that point?

for ( const auto & keyValue : myMap ) <---- Does this use the std::map::iterator, can I use std::map::reverse_iterator

SystemFun
  • 1,062
  • 4
  • 11
  • 21
  • There's some proposal for C++14 I think for allow iterator adaptor like you are asking but in C++11 the forward iterator (normal) is used. – NetVipeC Sep 12 '14 at 18:46

4 Answers4

2

According to the C++ Standard

— if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, beginexpr and end-expr are __range.begin() and __range.end(), respectively;

So in your case member functions begin() and end() of class std::map are called.

I suggested to the C+= Standard Committee to introduce something as

for ( auto x : reverse Container ) 

and till now I do not know the result of my suggesting though as far as I know the Committee is investigating the question.

As for your case then you can use some wrapper for an original standard container that will define member functions begin and end and will use reverse iterators of the container.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • See also [this answer](http://stackoverflow.com/a/8544956/648689), using `boost::adaptors::reverse()`. – JimB Jun 13 '15 at 12:13
1

There is a way to reverse iterate as stated in this answer, but it uses boost library.

The for ( const auto & keyValue : myMap ) uses a normal std::map::iterator though.

Another way to reverse iterate would be:

for (std::map::reverse_iterator iterator mymap.rbegin(); iterator != mymap.rend(); ++iterator)

Which is accepted by c++98 (not only c++11).

Community
  • 1
  • 1
t.pimentel
  • 1,465
  • 3
  • 17
  • 24
  • "default C++" you mean C++98? The C++ programming language has a history going back to 1979. – Mooing Duck Sep 12 '14 at 18:58
  • I don't know if it's from 98 or 03. I just meant that everything (that I now of) nowadays can run it with `::reverse_iterator`, but ROS, for example, doesn't run, by default, c++11. I'll correct it. Thanks for pointing that out. Is it from 98 or 03? Do you know? – t.pimentel Sep 12 '14 at 19:03
  • For what it's worth, `++iterator` is marginally more efficient than `iterator++`. – dlf Sep 12 '14 at 19:10
  • Thanks for the info. But why is it more efficient? – t.pimentel Sep 12 '14 at 19:13
  • 2
    Just because the postfix notation needs to copy the iterator, increment the original, and then return the copy. Many (most?) iterators are so lightweight that this doesn't matter, but some are not. – dlf Sep 12 '14 at 19:23
  • 1
    @t.pimentel: The STL was added to C++ in 1994, the next release of the standard was '98. '03 didn't change much to my knowledge. – Mooing Duck Sep 12 '14 at 19:27
1

In short, rule for range-based for is like this: it calls myMap.begin() and myMap.end() if they exist. Otherwise it calls begin(myMap) and end(myMap). So yes, in case of std::map it uses std::map::iterator.

If you want to iterate backwards you can write an adaptor yourself or use boost::adaptors::reverse.

See also this: C++11 reverse range-based for-loop

Update: here are full rules for range-based for (§6.5.4), for reference:

  • if _RangeT is an array type, begin-expr and end-expr are __range and __range + __bound, respectively, where __bound is the array bound. If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed;
  • if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, beginexpr and end-expr are __range.begin() and __range.end(), respectively;
  • otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespace std is an associated namespace.
Community
  • 1
  • 1
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
0

Yes the range-based for loop uses forward iteration. If you want to iterate backwards, then you need to do it yourself.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621