enable_if迭代器作为默认的模板参数?(enable_if iterator as a def

2019-06-26 22:58发布

我有一个这样的构造函数:

class MyClass
{
    template<class TI> MyClass(TI first, TI last);
};

template<class TI> MyClass::MyClass(TI first, TI last)
{
    ;
}

我想,以使只有TI是一个迭代这个构造函数(这意味着TI拥有的iterator_category我认为)。 如何做到这一点在C ++ 2011使用enable_if作为默认模板参数(在声明和定义)?

非常感谢你。

Answer 1:

这取决于你想要什么。 如果没有其他的过载,也可以是好的只有什么没有 。 如果一个类型传递不提供必要的操作,编译器将产生错误。

如果你真的想将其限制在迭代器,这是最好有这样做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 */ }


文章来源: enable_if iterator as a default template parameter?