enable_if迭代器作为默认模板参数? [英] enable_if iterator as a default template parameter?
问题描述
我有一个这样的构造函数:
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屋!