SkySurfer
SkySurfer

Reputation: 521

How to create iterator without type names?

For example I have a std::map<int, string> _m; and I want to iterate through it. So I have to write something like this: std::map<int, string>::iterator it = _m.begin().

The question is whether it is possible to create that iterator without using type names. Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?

UPDATE I forgot to say that I've to use old C++ standard.

Upvotes: 2

Views: 711

Answers (6)

Kaz Dragon
Kaz Dragon

Reputation: 6809

Since you specify that you're locked back in time to C++98, then about the best you have is whatever black magic is behind BOOST_AUTO.

#include <boost/typeof/typeof.hpp>
#include <map>
#include <string>

int main()
{
     std::map<int, std::string> m;
     BOOST_AUTO(it, m.begin());
}

BOOST_FOREACH was created as a similar thing for dealing with loops without having to specify iterator types.

#include <boost/foreach.hpp>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v;
    // populate v...

    BOOST_FOREACH(int const &i, v)
    {
        std::cout << i << "\n";
    }
}

Upvotes: 4

edmz
edmz

Reputation: 8494

Since you're trying to iterate over it, you may try one of the <algorithm>s such as std::for_each and pass a function

Upvotes: 2

If you're stuck to C++03, there's no way to refer to the type without spelling it out if you really need it. The best you could do is introduce a typedef (or more) so that you only have to type the long type once:

typedef std::map<int, string> TypeOfM;
typedef TypeOfM::iterator MIterator;
TypeOfM _m;

However, when you use standard library algorithms, you don't have to name the iterators explicitly:

std::for_each(_m.begin(), _m.end(), /* a functor */);

If Boost is an option, and you really only want iteration, you could also use Boost.Foreach. Unfortunately, that would still need a typedef, because the value_type of map is a pair and thus contains a , which would trip up the preprocessor:

typedef std::pair<const int, string> Pair;
BOOST_FOREACH(const Pair &p, _m)
{
  // Do whatever you need
}

Upvotes: 2

johannes
johannes

Reputation: 15969

The best general way is by using C++11's auto keyword as type. In later versions this can be done even better with range-bsed loops without any type information.

for (it : _m) {
    /* ... */
}

If you are stuck to old versions the only way to shorten the typename would be to create a template. This might make it more complex than writing the name, though. Something along those lines:

template <typename T> 
void do_foo(T it, T end) {
    for (; it < end; ++it) {
        /* ... */
    }
 }

 do_foo(_m.begin(), _m.end());

If wrapping your algorithm isn't the way you can also use a typedef to shorten it, but then you still have to type the name once.

Upvotes: 0

W.F.
W.F.

Reputation: 13988

Actually it is possible by using template function:

template <typename ITERATORTYPE> void myfunc(ITERATORTYPE it) {
    //.. do whatever you want with your it
}

Then just invoke the template:

myfunc(_m.begin());

Upvotes: 3

user229044
user229044

Reputation: 239291

You're after the auto keyword:

auto it = _m.begin();

Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?

Yes, this is the exact logic that lead to the introduction of auto.

If you cannot use C++11, you're stuck with things like typedef. The whole reason the new standard introduced auto is because of the exact problem you're facing - it's awkward to have to manually write out long type names all the time.

typedef std::map<int, string>::iterator map_itr;

map_itr it = _m.begin();

Upvotes: 6

Related Questions