Following is a Java method that returns an iterator
vector<string> types;
// some code here
Iterator Union::types()
{
return types.iterator();
}
I want to translate this code to C++. How can i return an iterator of vector from this method?
This will return an iterator to the beginning of types
:
std::vector<string>::iterator Union::types()
{
return types.begin();
}
However, the caller needs to know the end()
of vector types
as well.
Java's Iterator
has a method hasNext()
: this does not exist in C++.
You could change Union::types()
to return a range:
std::pair<std::vector<std::string>::iterator,
std::vector<std::string>::iterator> Union::types()
{
return std::make_pair(types.begin(), types.end());
}
std::pair<std::vector<std::string>::iterator,
std::vector<std::string>::iterator> p = Union::types();
for (; p.first != p.second; p.first++)
{
}
You'll want to have a begin
and end
method:
std::vector<string>::iterator Union::begin()
{
return types.begin();
}
std::vector<string>::iterator Union::end()
{
return types.end();
}
For completeness you might also want to have const
versions
std::vector<string>::const_iterator Union::begin()const
{
return types.begin();
}
std::vector<string>::const_iterator Union::end()const
{
return types.end();
}
Assuming that types is an attribute of the class Union, a nice, STL compliant, way to handle this is:
class Union
{
std::vector< std::string > types
public:
typedef std::vector< std::string >::iterator iterator;
iterator begin() { return types.begin(); }
iterator end() { return types.end(); }
};
An union is a container of its members. I would use begin
and end
to give back iterators to the first and after-the-last members, respectively.
The list of types is not IMO the primary iterable property of an union. So I would myself use the following, and reserve the plain begin
and end
for the member data itself.
std::vector<string>::const_iterator Union::types_begin() const {
return types.begin();
}
std::vector<string>::const_iterator Union::types_end() const {
return types.end();
}
Returning an iterator is easy. For example, you can return the first iterator in the vector types:
std::vector<std::string> types;
// some code here
std::vector<std::string>::iterator Union::returnTheBeginIterator()
{
return types.begin();
}
But C++ iterators are not Java iterators: They are not used the same way.
In Java (IIRC), you have more like an enumerator, that is, you use the method "next" to iterate from one item to the next. Thus, returning the Java iterator is enough to iterate from the begining to the end.
In C++, the iterator is designed to behave like a super-pointer. Thus, it usually "points" to the value, and using the operator ++, --, etc. (depending on the exact type of the iterator), you can move the iterator to "point" to the next, previous, etc. value in the container.
Usually, you want to iterate from the beginning to the end.
This, you need to return either the whole collection (as "const", if you want it to be readonly), and let the user iterate the way he/she wants.
Or you can return two iterators, one for the beginning, and one for the end. So you could have:
std::vector<std::string>::iterator Union::typesBegin()
{
return types.begin();
}
std::vector<std::string>::iterator Union::typesEnd()
{
return types.end();
}
And the, you can iterate from the beginning to the end, in C++03:
// alias, because the full declaration is too long
typedef std::vector<std::string> VecStr ;
void foo(Union & p_union)
{
VecStr::iterator it = p_union.typesBegin() ;
VecStr::iterator itEnd = p_union.typesEnd() ;
for(; it != itEnd; ++it)
{
// here, "*it" is the current string item
std::cout << "The current value is " << *it << ".\n" ;
}
}
If you provide the full container instead of only its iterators, in C++11, it becomes easier, as you can use the range-for loop (as the foreach in Java and C#):
void foo(std::vector<std::string> & p_types)
{
for(std::string & item : p_types)
{
// here, "item " is the current string item
std::cout << "The current value is " << item << ".\n" ;
}
}
P.S.: Johannes Schaub - litb is right in using the "const" qualifier whenever possible. I did not because I wanted to avoid to dilute the code, but in the end, "const" is your friend.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With