这取决于你想要什么。如果没有其他重载,那就可以完全不用任何东西。如果传递的类型没有提供必要的操作,编译器将产生一个错误。
如果你真的想限制为迭代器,最好使用static_assert
来实现,因为它会生成具有良好自定义错误消息的错误,而不是“模棱两可的函数调用,这里是我找到的所有弯道超车: 接下来是无休止的重载列表”或“找不到函数,请自己找”。
如果存在另一个与之冲突的模板重载,那么确实需要一些enable_if的东西。我写了一篇关于如何使用C++11特性的enable_if以及为什么默认模板参数并不是很好的选择的博客文章。我最终采用了类似于以下方式的方法:
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::MyClass(TI first, TI last)
现在你所需要的就是一个测试的特性。我认为测试iterator_category
的存在已经足够了,但是应该使用std :: iterator_traits
来完成,因为指针也是迭代器,但没有嵌套的typedefs。
可以使用通常使用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::MyClass(TI first, TI last,
typename std::iterator_traits<T>::iterator_category*)