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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…