Reputation: 117691
I'm sorry for the very vague title, I really didn't know how to title this question.
Let's say I have this:
std::list<std::string> msgs;
for (std::list<std::string>::iterator it = msgs.begin(); it < msgs.end(); it++) {
// ...
}
For me, this is hard to to read. The std::list<std::string>::iterator
almost seems like a magic number, especially if the declaration of msgs
is far away, like in an header file. IMO it would be easier to read and much more semantic if it were something like this:
std::list<std::string> msgs;
for (msgs.iterator it = msgs.begin(); it < msgs.end(); it++) {
// ...
}
Now, this is obviously illegal C++. But my question is, is there a way of implementing something that supports writing iterator declarations like this?
Upvotes: 11
Views: 3227
Reputation: 35901
If you provide a typedef it will make life a lot easier:
typedef std::list<std::string>::iterator ListIterator;
for( ListIterator it = msgs.begin(); it != msgs.end(); ++it ){}
Other than that, c++0x does it for you by providing the auto keyword:
for( auto it = msgs.begin(); it != msgs.end(); ++it ){}
edit like 5 years after date, but I updated <
tp !=
and using preincrement because that's actually what I've been doing for ages, and makes more sense to me, to the point it makes me wonder how I ever wrote this answer not using that
Upvotes: 16
Reputation: 179819
The canonical solution is
std::for_each(msgs.begin(), msgs.end(), ... );
Before C++0x, writing the ...
bit used to be a bit hard (if it was anything complex), but we now have lambda's.
Upvotes: 0
Reputation: 385154
There are two practical, canonical approaches:
typedef std::list<int> list_t;
list_t l;
// later:
for (list_t::iterator it = l.begin(), end = l.end(); it != end; ++it) {}
And the C++0x-only auto
:
std::list<int> l;
// later:
for (auto it = l.begin(), end = l.end(); it != end; ++it) {}
In addition, C++0x allows:
std::list<int> l;
// later:
for (decltype(l)::iterator it = l.begin(), end = l.end(); it != end; ++it)
std::cout << *it << ", ";
I think that this is the closest match to what you were specifically asking (even if it's not necessarily the best solution).
The downside is that the ability to apply the scope operator (::
) to decltype
link was only voted into the working paper relatively recently, and I'm not aware of any compilers that support it yet (GCC 4.5.1 does not).
Upvotes: 4
Reputation: 76788
All containers have these typedef
s to enable the writing of very generic code. Consider the following function-template:
template<class T>
void foo(const T& container) {
for(T::const_iterator it = T.begin(); it != T.end(); it++) {
// do stuff
}
}
This enables you to write code that can work with any object that has defines a type const_iterator
and a method begin()
and end()
.
In C++0x the problem is solved with the introduction of the auto
keyword:
for(auto it = container.begin(); it != container.end(); it++) {
// do stuff
}
Upvotes: 0
Reputation: 4779
You can use typedef to clean that up:
typedef std::list<std::string>::iterator string_iterator;
std::list<std::string> msgs;
for (string_iterator it = msgs.begin(); it != msgs.end(); it++) {
// ...
}
Upvotes: 1