Reputation: 2527
C++ rookie here. I wrote a function that returns an iterator from a vector, and I want to use this iterator to iterate through the vector from beginning to end. However, the vector iterator is used like this
for (auto iterator = vec.begin(); iterator != vec.end(); iterator ++) {
// do something here
}
which means I also need a vec.end() for this to work. Is there anyway I can only use vec.begin() to iterate through a vector, as I commonly did in python
for value in some_iterator:
# do something
edit: some irrelevant update:
I see some comments about my python iterator vs iterable. The iterator can indeed be used this way (at least in Python 3). For example:
some_list = [1,2,3,4]
some_iterator = iter(some_list)
for value in some_iterator:
print(value)
Upvotes: 0
Views: 1665
Reputation: 4926
As others have already pointed out, saying:
for value in some_iterator:
# do something
is not correct: you are iterating in an array, or more generally in an "iterable", by using it's internal __iter__
iterators. So it's more correct:
for value in some_iterable:
# do something
Iterables in python are "containers" in C++. std::vector
is a container.
I think you have two options:
The "old way" was to pass an empty vector by reference to the function, and let the function fill the vector.
However I usually don't like to use std::pair
for this kind of operations, but to forge my temporary type for the specific aim.
For example, this could be the signature of your function:
template<typename TYPE>
struct GetRangeResult {
std::vector<TYPE>::const_iterator begin;
std::vector<TYPE>::const_iterator end;
};
template<typename TYPE>
GetRangeResult<TYPE> GetRange(/* your args */) {
GetRangeResult<TYPE> result;
// the method here fills result.begin and result.end
return result;
}
and you would use it:
auto range = GetRange(/* your args */);
for (auto it=range.begin; it!=range.end; ++it) {
...
}
Again you cannot do it if the vector is temporary within the GetRange()
function.
Upvotes: 2
Reputation: 596713
I wrote a function that returns an iterator from a vector, and I want to use this iterator to iterate through the vector from beginning to end.
You need 2 iterators in order to iterate through a container - the starting iterator, and the ending iterator. For instance, change your function to return a std::pair
of iterators instead of a single iterator, then you can iterate, eg:
template<typename Container>
std::pair<Container::iterator, Container::iterator> func(Container &c) {
return std::make_pair(c.begin(), c.end());
}
auto p = func(vec);
for (auto iter = p.first; iter != p.second; ++iter) {
// do something here
}
Is there anyway I can only use vec.begin() to iterate through a vector
No. Without a second iterator, you wouldn't know when to stop iterating.
as I commonly did in python
The closest thing to that is a range-based for loop, but that requires having access to the vector itself, it using iterators manually (the loop uses iterators internally for you):
for (auto &elem : vec) {
// do something here
}
Upvotes: 1
Reputation: 62894
C++ is not Python. A pair of std::vector::iterator
s is required to denote a range (the start and one past the end). If you only have one Iterator, there's nothing you can safely do with it (besides compare it with itself, which is vacuously true
).
You are confusing the python concept of a Python iterable, which is a sequence of values. This is distinct from an Python iterator, which is an object with a next()
(__next__()
in Python 3) that returns the next value or throws StopIteration
for value in some_iterable:
#do something here
Which corresponds to roughly
_iter = some_iterable.__iter__()
while True:
try
value = _iter.__next__()
except StopIteration:
break;
#do something here
You probably want a ranged-for statement
for (auto val : vec){
// do something here
}
Which corresponds to roughly
{
auto && __range = vec;
for (auto __begin = begin(__range), __end = end(__range); __begin != __end; ++__begin) {
auto val = *__begin;
// do something here
}
}
(In both versions, the local variables with leading _
don't actually exist, the names are expository)
A C++ iterator splits out the returning of values (*it
and it->
) from moving (++it
etc); and from stopping (it != end
), where end
points one past the final element. A Python iterator does it all in next()
.
Upvotes: 7
Reputation: 1420
There is no way to get the a reference to the original container from an iterator. That means if you have a function that, say, returns an iterator to the mid point of a vector it is effectively useless unless you know which vector it came from.
Your options are to either:
std::find
).Without knowing the purpose of the function it's hard to give more specific advice. I suspect there is probably a better that of structuring your code.
Upvotes: 0