Vin*_*ent 2 c++ templates sfinae enable-if c++11
我有一个像这样的构造函数:
class MyClass
{
template<class TI> MyClass(TI first, TI last);
};
template<class TI> MyClass::MyClass(TI first, TI last)
{
;
}
Run Code Online (Sandbox Code Playgroud)
我想只在TI是一个迭代器时启用这个构造函数(这意味着我认为TI有一个iterator_category).如何在C++ 2011中使用enable_if作为默认模板参数(在声明和定义中)?
非常感谢你.
R. *_*des 11
这取决于你想要什么.如果没有其他重载,它可以没有任何东西.如果传递的类型不提供必要的操作,编译器将产生错误.
如果你真的想把它限制为迭代器,最好用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 */ }
Run Code Online (Sandbox Code Playgroud)
您现在需要的只是测试的特征.我认为测试存在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)) {};
Run Code Online (Sandbox Code Playgroud)
总而言之,这可以通过使用默认函数参数的传统技术来完成:
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 */ }
Run Code Online (Sandbox Code Playgroud)