这取决于你想要什么。如果没有其他重载,则什么都没有也可以。如果传递的类型未提供必要的操作,编译器将产生错误。
如果您真的想将其限制为迭代器,最好使用 a 这样做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 */ }