C为什么SFINAE只有一个类模板参数才会失败?

前端之家收集整理的这篇文章主要介绍了C为什么SFINAE只有一个类模板参数才会失败?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用 this answer样式的SFINAE,以便通过使用适当的成员函数调用泛型矢量对象.例如,下面的代码首先调用operator [](int)const,如果不存在则operator()(int)const:
  1. template<int I> struct rank : rank<I-1> { static_assert(I > 0,""); };
  2. template<> struct rank<0> {};
  3.  
  4. template<typename VectorType>
  5. struct VectorWrapper
  6. {
  7. auto get(int i) const
  8. {
  9. return get(v,i,rank<5>());
  10. }
  11.  
  12. template<typename V,typename = std::enable_if_t<has_bracket_operator<const V>::value> >
  13. auto get(V const& v,int i,rank<2>) const
  14. {
  15. return v[i];
  16. }
  17.  
  18. template<typename V,typename = std::enable_if_t<has_parenthesis_operator<const V>::value> >
  19. auto get(V const& v,rank<1>) const
  20. {
  21. return v(i);
  22. }
  23.  
  24. VectorType v;
  25. };

根据this thread中的建议设置has_bracket_operator和has_parenthesis_operator特征,整个编译和seems to work.

但是,从第一个开始,将成员向量传递给重载的类模板似乎是不必要的,所以我尝试设置相同而不传递它.为此,我将模板参数V替换为用于设置类模板的VectorType参数:

  1. template<typename = std::enable_if_t<has_bracket_operator<VectorType>::value> >
  2. auto get(int i,rank<2>) const
  3. {
  4. return v[i];
  5. }
  6.  
  7. template<typename = std::enable_if_t<has_parenthesis_operator<VectorType>::value> >
  8. auto get(int i,rank<1>) const
  9. {
  10. return v(i);
  11. }

但是,现在,编译失败(在gcc 5.1.0中),并显示以下错误消息:

  1. /usr/local/include/c++/5.1.0/type_traits: In substitution of 'template<bool _Cond,class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = has_parenthesis_operator<std::vector<int> >::value; _Tp = void]':
  2. main.cpp:46:10: required from 'struct VectorWrapper<std::vector<int> >'
  3. main.cpp:59:38: required from here
  4. /usr/local/include/c++/5.1.0/type_traits:2388:61: error: no type named 'type' in 'struct std::enable_if<false,void>'
  5. using enable_if_t = typename enable_if<_Cond,_Tp>::type;

DEMO

问题:

>这个编译错误的原因是什么?
>除了我的第一个代码块之外,是否有适当的解决方法? (也就是说,保留了通常的编码风格 – 一个人不必通过成员).

解决方法

SFINAE来自[temp.deduct] / 8,强调我的:

If a substitution results in an invalid type or expression,type deduction fails. An invalid type or expression is
one that would be ill-formed,with a diagnostic required,if written using the substituted arguments. [ Note:
If no diagnostic is required,the program is still ill-formed. Access checking is done as part of the substitution
process. —end note ] Only invalid types and expressions in the immediate context of the function type and
its template parameter types can result in a deduction failure.

直接上下文是模板声明中的内容.在您的初始示例中:

  1. template<typename V,typename = std::enable_if_t<has_bracket_operator<const V>::value> >
  2. auto get(V const& v,rank<2>) const

V在紧邻的上下文中,因此enable_if上的替换失败只是一个演绎失败.

但是,在你的第二个例子中:

  1. template<typename = std::enable_if_t<has_bracket_operator<VectorType>::value> >
  2. auto get(int i,rank<2>) const

VectorType不在get的直接上下文中,因此这里的失败不会是演绎失败,这将是一个很难的错误.

除非VectorType碰巧拥有所有这些运算符.

任何模板问题的解决方案是只添加更多模板.在这种情况下,通过引入另一种类型强制VectorType在直接上下文中:

  1. template<typename T=VectorType,typename = std::enable_if_t<has_bracket_operator<T>::value> >
  2. auto get(int i,rank<2>) const

调用get<>().

猜你在找的C&C++相关文章