数年後にここに来て、C++11 と C++14 がそのようなことをより簡単にできるようにします。イテレータは、本質的に、逆参照可能でインクリメント可能なものです。入力 iteratorの場合も同様です。後者で行きましょう - それはあなたが望むもののように見えるからです.
最も簡単なバージョンは、次を使用すること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
それぞれ、反復子の差分型、値型、および反復子カテゴリとして定義されます。
したがって、 iterator トレイトを定義して、単純にそれをチェックできます。
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
、イテレータではありません。