几年后来到这里,C++11 和 C++14 使做这些事情变得容易得多。迭代器的核心是可取消引用的、可递增的。如果它是一个输入迭代器,那么也具有可比性。让我们选择后者 - 因为这看起来像你想要的。
最简单的版本是使用void_t
:
template <typename... >
using void_t = void;
基本情况:
template <typename T, typename = void>
struct is_input_iterator : std::false_type { };
有效的案例专业化:
template <typename T>
struct is_input_iterator<T,
void_t<decltype(++std::declval<T&>()), // incrementable,
decltype(*std::declval<T&>()), // dereferencable,
decltype(std::declval<T&>() == std::declval<T&>())>> // comparable
: std::true_type { };
别名:
template <typename T>
using is_input_iterator_t = typename is_input_iterator<T>::type;
无需依赖iterator_category
或使用繁琐的 C++03 风格的重载决议来检查事物。表达式 SFINAE 就是它所在的位置。
正如 Wakely 先生在评论中指出的那样,[iterator.traits] 要求:
要求如果Iterator
是迭代器的类型,则类型
iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::iterator_category
分别定义为迭代器的差分类型、值类型和迭代器类别。
所以我们可以定义我们的迭代器特征来简单地检查:
template <class T, class = void>
struct is_iterator : std::false_type { };
template <class T>
struct is_iterator<T, void_t<
typename std::iterator_traits<T>::iterator_category
>> : std::true_type { };
如果iterator_traits<T>::iterator_category
是格式错误的,则T
不是迭代器。