模板专门化和enable_if问题 [英] Template specialization and enable_if problems

查看:207
本文介绍了模板专门化和enable_if问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了关于适当使用enable_if和模板专用化的问题。



修改示例后(出于保密原因),这里有一个类似的示例: / p>


我有一个名为less的函数,用于检查第一个arg小于第二个
arg。让我们说,我想有2种不同的实现
取决于输入的类型-1整数的实现和
的另一个double。


我到目前为止的代码看起来像这样 -

  #include< type_traits> 
#include< iostream>

template< class T,
class = typename std :: enable_if< std :: is_floating_point< T> :: value> :: type&
bool less(T a,T b){
// ...
}

模板< class T,
class = typename std :: enable_if< std :: is_integral< T> :: value> :: type>
bool less(T a,T b){
// ...
}

int main(){
float a;
float b;
less(a,b);
return 0;
}

上述代码不能编译,因为它说我重新定义



错误是:

  Z.cpp: 15:19:error:template parameter redefines default argument 
class = typename std :: enable_if< std :: is_integral< T> :: value> :: type>

^
Z.cpp:9:19:注意:之前定义的默认模板参数
class = typename std :: enable_if< std :: is_floating_point< T> value> :: type>
^

Z.cpp:16:11:error:redefinition of'less'
bool less(T a,T b){
^

Z.cpp:10:11:注意:以前的定义在这里
bool less(T a,T b){
^

Z.cpp: 23:5:错误:没有匹配函数调用'less'
less(a,b);
^ ~~~

Z.cpp:15:43:注意:候选模板被忽略:被'enable_if'禁用
[with T = float]
= typename std :: enable_if< std :: is_integral< T> :: value> :: type>
^
生成3个错误。有人可以指出这里的错误是什么?


h2_lin>解决方案

默认模板参数不是函数模板签名的一部分。所以在你的例子中,你有两个相同的重载,这是非法的。 clang抱怨缺省参数的重新定义(根据§14.1/ 12 [temp.param],这是非法的),而gcc产生以下错误消息:


错误:redefinition'模板< class T,class> bool less(T,T)'


要修复错误,请移动 enable_if 从默认参数到虚拟模板参数的表达式

 模板< class T,
typename std :: enable_if< std :: is_floating_point< T> :: value,int> :: type * = nullptr>
bool less(T a,T b){
// ...
}

模板< class T,
typename std: :enable_if< std :: is_integral< T> :: value,int> :: type * = nullptr>
bool less(T a,T b){
// ....
}






另一种选择是在返回类型中使用 enable_if ,虽然我觉得这更难阅读。

 模板< class T> 
typename std :: enable_if< std :: is_floating_point< T> :: value,bool> :: type
less(T a,T b){
// ....
}

template< class T>
typename std :: enable_if< std :: is_integral< T> :: value,bool> :: type
less(T a,T b){
// ....
}


I am running into a problem regarding the appropriate usage of enable_if and template specialization.

After modifying the example (for confidentiality reasons), here's a comparable example:

I have function called "less" that checks if 1st arg is less than 2nd arg. Let's say I want to have 2 different kinds of implementations depending on the type of input - 1 implementation for integer and another for double.

The code that I have so far looks like this -

#include <type_traits>
#include <iostream>

template <class T,
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

template <class T,
          class = typename std::enable_if<std::is_integral<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

int main() {
    float a;
    float b;
    less(a,b);
    return 0;
}

The above code does not compile because - It says that I am re-defining the less method.

Errors are:

Z.cpp:15:19: error: template parameter redefines default argument
          class = typename std::enable_if<std::is_integral<T>::value>::type>

                  ^
Z.cpp:9:19: note: previous default template argument defined here
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
                  ^

Z.cpp:16:11: error: redefinition of 'less'
     bool less(T a, T b) {
          ^

Z.cpp:10:11: note: previous definition is here
     bool less(T a, T b) {
          ^

Z.cpp:23:5: error: no matching function for call to 'less'
    less(a,b);
    ^~~~

Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if'
      [with T = float]
          class = typename std::enable_if<std::is_integral<T>::value>::type>
                                          ^
3 errors generated.

Can someone point out what's the mistake here?

解决方案

Default template arguments are not part of the signature of a function template. So in your example you have two identical overloads of less, which is illegal. clang complains about the redefinition of the default argument (which is also illegal according to §14.1/12 [temp.param]), while gcc produces the following error message:

error: redefinition of 'template<class T, class> bool less(T, T)'

To fix the error move the enable_if expression from default argument to a dummy template parameter

template <class T,
          typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}

template <class T,
          typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}


Another option is to use enable_if in the return type, though I feel this is harder to read.

template <class T>
      typename std::enable_if<std::is_floating_point<T>::value, bool>::type 
      less(T a, T b) {
  // ....
}

template <class T>
     typename std::enable_if<std::is_integral<T>::value, bool>::type 
     less(T a, T b) {
  // ....
}

这篇关于模板专门化和enable_if问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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