I have a function that needs to enumerate an iterator multiple times, but according to MSDN, \"Once you increment any copy of an input iterator, none of the other copies can
You can use SFINAE and replace bool
by:
typename enable_if<
is_same<typename std::iterator_traits<It>::iterator_category,
std::forward_iterator_tag>::value,
bool>::type
You may need to define is_same
and enable_if
yourself if you don't want to pull them from Boost or TR1:
template <typename A, typename B>
struct is_same { static const bool value = false; };
template <typename T>
struct is_same<T, T> { static const bool value = true; };
template <bool, typename> struct enable_if { };
template <typename T> struct enable_if<true, T> { typedef T type; };
Not tested but you could try something along the lines of:
template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice_Interal(const It &begin, const It &end, TCallback callback,
std::forward_iterator_tag)
{
//do your things
}
template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice(const It &begin, const It &end, TCallback callback)
{
EnumerateTwice_Internal(begin, end, callback,
typename std::iterator_traits<It>::iterator_category());
}
You can do this using std::enable_if
:
#include <iterator>
#include <type_traits>
#include <utility>
template <typename It, typename TCallback>
typename std::enable_if<std::is_base_of<std::forward_iterator_tag,
typename std::iterator_traits<It>::iterator_category>::value,
bool>::type
EnumerateTwice(It begin, It end, TCallback) {
...
}
This uses class from C++11 but all of this can be done in C++03 as well.
To expand on rodrigo's answer -- I found this solution, and thought it's worth mentioning:
struct True { unsigned char _[2]; operator bool() const { return true; } };
char is_forward_iterator(std::input_iterator_tag const *) { return 0; }
True is_forward_iterator(std::forward_iterator_tag const *) { return True(); }
Now, if you want to check it inside some function, you can say:
if (is_forward_iterator(static_cast<iterator_traits<It>::iterator_category*>(0)))
{
...
}
and if you want to check it within templates, you can check for:
sizeof(
is_forward_iterator(static_cast<iterator_traits<It>::iterator_category*>(0))
) > 1
with the primary advantage of this method being that it avoids declaring templates (e.g. for better compilation speed).