それはあなたが望むものに依存します。他に過負荷がない場合は、何もしなくても問題ありません。必要な操作を提供しない型が渡されると、コンパイラーはエラーを生成します。
本当にイテレータに限定したい場合はstatic_assert
、「あいまいな関数呼び出しの代わりに、素敵なカスタムエラーメッセージでエラーを生成するので、これを行うことをお勧めします。これが私が見つけることができるすべての膨大な数のオーバーロードです:無限のリストに従いますオーバーロードの「または「機能が見つかりませんでした。自分で見つけてください」。
競合する別のテンプレート化されたオーバーロードがある場合は、実際にenable_ifが必要です。enable_ifをC++11の機能で使用する方法と、デフォルトのテンプレートパラメーターがあまり適切でない理由についてブログに投稿しました。私は代わりにこのようなもので解決しました:
enum class enabler {};
template <typename Condition>
using EnableIf = typename std::enable_if<Condition::value, enabler>::type;
class MyClass
{
template<class TI, EnableIf<is_iterator<TI>>...> MyClass(TI first, TI last);
};
template<class TI, EnableIf<is_iterator<TI>>...> MyClass::MyClass(TI first, TI last)
{ /* blah */ }
今必要なのは、テストの特性だけです。の存在をテストするiterator_category
だけで十分だと思いますstd::iterator_traits
が、ポインターはイテレーターであり、ネストされたtypedefがないため、を使用してテストする必要があります。
これは、SFINAEを使用する通常の手法で実行できます。C ++ 11では、次のことを行います。
template <typename T>
struct sfinae_true : std::true_type {};
struct is_iterator_tester {
template <typename T>
static sfinae_true<typename std::iterator_traits<T>::iterator_category> test(int);
template <typename>
static std::false_type test(...);
};
template <typename T>
struct is_iterator : decltype(is_iterator_tester::test<T>(0)) {};
とはいえ、これはデフォルトの関数パラメーターを使用する従来の手法で実行できた可能性があります。
class MyClass
{
template<class TI>
MyClass(TI first, TI last,
typename std::iterator_traits<T>::iterator_category* = nullptr)
};
template<class TI>
MyClass::MyClass(TI first, TI last,
typename std::iterator_traits<T>::iterator_category*)
{ /* blah */ }