Reputation: 17553
Is there a simple way to compare an iterator with an int?
I have a loop like this:
for (std::vector<mystruct>::const_iterator it = vec->begin(); it != vec->end(); ++it)
Instead of looping over the entire vector, I would like to just loop over the first 3 elements. However, the following does not compile:
for (std::vector<mystruct>::const_iterator it = vec->begin(); it < 3; ++it)
It there a good way to achieve the same effect?
Upvotes: 2
Views: 3474
Reputation: 1737
Sure, you can simply go three elements past the beginning.
for (std::vector<mystruct>::const_iterator it = vec->cbegin(); it != vec->cbegin() + 3; ++it)
However, that might be error prone since you might try to access beyond the end in the case that the vector is fewer than 3 elements. I think you'd get an exception when that happens but you could prevent it by:
for(std::vector<mystruct>::const_iterator it = vec->cbegin(); it != vec->cend() && it != vec->cbegin() + 3; ++it)
Note the use of cbegin() and cend() since you asked for a const_iterator, although these are only available in c++11. You could just as easily use begin() and end() with your const_iterator.
Upvotes: 0
Reputation: 13505
since it's a vector, why not just access its position directly ?
if (vec->size() > 0)
{
for (int i =0; i<3 && i< vec->size(); i++)
{
// vec[i] can be accessed directly
//do stuff
}
}
Upvotes: 4
Reputation: 275395
I'd want to be careful, because you can easily run into fencepost bugs.
This works on random access containers (like vector
and array
), but doesn't do ADL on begin
because I'm lazy:
template<typename Container>
auto nth_element( Container&& c, std::size_t n )->decltype( std::begin(c) )
{
auto retval = std::begin(c);
std::size_t size = std::end(c) - retval;
retval += std::min( size, n );
return retval;
}
It returns std::end(c)
if n
is too big.
So you get:
for( auto it = vec->cbegin(); it != nth_element(vec, 3); ++it) {
// code
}
which deals with vectors whose size is less than 3 gracefully.
The basic core of this is that on random access iterators, the difference of iterators is ptrdiff_t
-- an integral type -- and you can add integral types to iterators to move around. I just threw in a helper function, because you should only do non-trivial pointer arithmetic (and arithmetic on iterators is pointer arithmetic) in isolated functions if you can help it.
Supporting non-random access iterators is a matter of doing some traits checks. I wouldn't worry about that unless you really need it.
Note that this answer depends on some C++11 features, but no obscure ones. You'll need to #include <iterator>
for std::begin
and std::end
and maybe <algorithm>
for std::min
.
Upvotes: 3
Reputation: 53047
std::next(vec->begin(), 3);
will be the the iterator 3 places after the first, and so you can compare to it:
for (std::vector<mystruct>::const_iterator it = vec->begin(); it != std::next(vec->begin(), 3); ++it)
Your vector will need to have at least 3 elements inside it though.
Upvotes: 4