I have an stl iterator resulting from a std::find() and wish to test whether it is the last element. One way to write this is as follows:
mine *match = some
You would first need a way to determine if an iterator is a reverse one, which was ingeniously shown here :
#include <iterator>
#include <type_traits>
template<typename Iter>
struct is_reverse_iterator : std::false_type { };
template<typename Iter>
struct is_reverse_iterator<std::reverse_iterator<Iter>>
: std::integral_constant<bool, !is_reverse_iterator<Iter>::value>
{ };
Then you could have two flavors for performing the test
template<bool isRev> // for normal iterators
struct is_last_it
{
template<typename It, typename Cont>
static bool apply(It it, Cont const &cont)
{ // you need to test with .end()
return it != cont.end() && ++it == cont.end();
}
};
template<> // for reverse iterators
struct is_last_it<true>
{
template<typename It, typename Cont>
static bool apply(It it, Cont const &cont)
{ // you need to test with .rend()
return it != cont.rend() && ++it == cont.rend();
}
};
And a single interface function
template<typename It, typename Cont>
bool is_last_iterator(It it, Cont const &cont)
{
return is_last_it<is_reverse_iterator<It>::value>::apply(it, cont);
};
Then for every type of iterator (reverse / straight) you can use the interface function
int main()
{
std::vector<int> v;
v.push_back(1);
auto it (v.begin()), ite(v.end()); // normal iterators
auto rit(v.rbegin()), rite(v.rend()); // reverse iterators
std::cout << is_last_iterator(it, v) << std::endl;
std::cout << is_last_iterator(ite, v) << std::endl;
std::cout << is_last_iterator(rit, v) << std::endl;
std::cout << is_last_iterator(rite, v) << std::endl;
return 0;
}
Note that some implementation (apart from std::begin()
and std::end()
which are common enough, also include std::rbegin()
and std::rend()
. When possible use this set of functions instead of member .begin()
etc.
Here's another potential solution:
template<class Iterator, class Container> bool is_last(Iterator it, const Container& cont)
{
// REQUIREMENTS:
// the iterator must be a valid iterator for `cont`
if( it == cont.end() )
return false; // or throw if you prefer
return (++it) == cont.end();
}
A better way would be to copy the iterator and then increment it. You can then test the incremented version against end()
. If you're careful, you can use a post-increment to avoid the need to formally copy it.
if (++vector<mine*>::iterator(itr) == Mine.end())
If itr could already be at the end:
if (itr == Mine.end() || ++vector<mine*>::iterator(itr) == Mine.end())
Or, based on GMan's answer but a bit safer:
if (Mine.Length() == 0 || itr == Mine.End() || &*itr == &Mine.back())
I just fixed the last one again, as I was wrong about &*
.