Reputation: 521
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
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
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
Reputation: 171127
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
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
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
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