如何定义is_iterator类型特征?

101*_*010 11 c++ iterator type-traits c++11 c++14

  • 我正在尝试编写一个is_iterator<T>类型特征.凡当T是一个迭代器类型is_iterator<T>::value == true,否则是is_iterator<T>::value == false.

  • 到目前为止我尝试了什么:


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 {};
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO


问:是否有更合适的方式来定义is_iterator类型特征而不是上面显示的类型特征?

Jon*_*ely 8

正如我在评论中所说,这里介绍的解决方案依赖iterators_traits于某些实现中的非便携属性.根据C++ 03和C++ 11标准,iterator_traits仅为迭代器(以及指针的特殊情况)定义,因此任何其他用途都是未定义的行为.具体而言,使用iterator_traits<T>::pointer在SFINAE背景不能保证工作,因为实例iterator_traits<T>会参考T::value_type,T::pointer,T::iterator_category等,并且这种情况发生"立即语境"里SFINAE不适之外.

C++ 14 将修复本应修复的问题(它发生在C++ 14之后的DR 2408),但对于C++ 11,定义的安全方法is_iterator是编写一个特征来检查所有必需的操作迭代器必须定义.所有迭代器都需要支持的唯一操作是operator*增量前和后增量.不幸的是,可能存在定义那些不是有效迭代器的操作的类型,因此编写正确的特征非常困难.


Pra*_*ian 6

std::iterator_traits<T>::pointer如果是不是指针的类型,例如 if ,则检查失败T = std::ostream_iterator<U>

我认为更好的测试可能是是否std::iterator_traits<T>::iterator_categorystd::input_iterator_tag或派生类型,或std::output_iterator_tag

template <class, class Enable = void> struct is_iterator : std::false_type {};
template <typename T> 
struct is_iterator
<T, 
 typename std::enable_if<
    std::is_base_of<std::input_iterator_tag, typename std::iterator_traits<T>::iterator_category>::value ||
    std::is_same<std::output_iterator_tag, typename std::iterator_traits<T>::iterator_category>::value 
 >::type> 
 : std::true_type {};
Run Code Online (Sandbox Code Playgroud)