enable_if迭代器作为默认模板参数? [英] enable_if iterator as a default template parameter?

查看:108
本文介绍了enable_if迭代器作为默认模板参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a constructor like that :

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作为默认模板参数(在声明和定义中)?

I would like to enable this constructor only if TI is an iterator (that means TI has an iterator_category I think). How to do that in C++ 2011 using an enable_if as a default template parameter (in the declaration and in the definition) ?

非常感谢。

推荐答案

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

It depends on what you want. If there are no other overloads, it can be ok with just nothing at all. The compiler will produce an error if a type is passed that doesn't provide the necessary operation.

如果你真的想限制到迭代器,最好这样做与 static_assert ,因为它产生一个错误与一个漂亮的自定义错误消息,而不是模糊的函数调用,这里是所有的gazillion重载我可以找到:

If you really want to limit it to iterators, it's preferable to do so with a static_assert, since it produces an error with a nice custom error message, instead of "ambiguous function call, here are all the gazillion overloads I could find: follows endless list of overloads" or "could not find function, find it yourself".

如果有另一个模板的重载冲突,那么你确实需要一些enable_if的东西。我写了一篇关于使用带C ++ 11功能的enable_if 的博文,以及为什么默认模板参数不是很好。我用这样的代替:

If there is another templated overload that conflicts, then you do indeed need some enable_if thing. I wrote a blog post about using enable_if with C++11 features, and why default template parameters are not very good for that. I settled with something like this instead:

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。

All that you need now is a trait for the test. I think testing for the existence of iterator_category is enough, but it should be done with std::iterator_traits, because pointers are iterators and don't have nested typedefs.

这可以使用通常使用SFINAE的技术。使用C ++ 11,我执行以下操作:

That can be done with the usual techniques that use SFINAE. With C++11, I do the following:

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)) {};

这一切都可以用传统的使用默认函数参数的方法来完成: / p>

All that said, this could have been done with the traditional technique of using a defaulted function parameter:

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迭代器作为默认模板参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆