101010 101010 - 8 days ago 6x
C++ Question

How to define is_iterator type trait?

  • I'm trying to code a
    type trait. Where when
    is an iterator type
    is_iterator<T>::value == true
    otherwise is
    is_iterator<T>::value == false

  • What I tried so far:

template <class, class Enable = void>
struct is_iterator : std::false_type {};

template <typename T>
struct is_iterator<T, typename std::enable_if<std::is_pointer<typename
std::iterator_traits<T>::pointer>::value>::type> : std::true_type {};


Q: Is there a more proper way to define a
type trait than the one displayed above?


As I said in comments, the solutions presented here rely on non-portable properties of iterators_traits in some implementations. According to the C++03 and C++11 standards, iterator_traits is only defined for iterators (and the special case of pointers) so any other use is undefined behaviour. Specifically, using iterator_traits<T>::pointer in a SFINAE context isn't guaranteed to work, because instantiating iterator_traits<T> will refer to T::value_type, T::pointer, T::iterator_category etc. and that happens outside the "immediate context" where SFINAE doesn't apply.

C++14 will fix that was supposed to fix that (it happened post-C++14 with DR 2408), but for C++11 the safe way to define is_iterator is to write a trait that checks for all the required operations an iterator must define. The only operations that all iterators are required to support are operator* and pre- and post-increment. Unfortunately, there can be types that define those operations which are not valid iterators, so writing a correct trait is quite hard.