【问题标题】:Distinguishing integer from floating point types in a template在模板中区分整数和浮点类型
【发布时间】:2013-11-14 18:12:15
【问题描述】:

我想对几种整数类型(16、32、64 位)和浮点类型(float、double、long double)执行类似但不相同的计算。大多数代码是相同的,但对于 int 和 float,某些部分需要以不同的方式完成。例如,比较整数可以用 a==b 来完成,而比较浮点数应该用 abs(a-b) 来完成

这样做的一种方法是将 int 和 float 之间不同的代码部分隔离到小函数中,并为每种类型专门化模板。但是,我不想为每个整数类型复制粘贴相同的代码,为每个浮点类型复制粘贴另一个代码。因此问题是:是否可以一次为多种类型专门化模板函数?如果合法,语义上类似于以下内容:

template<>
bool isEqual< short OR long OR long long >( T a, T b ) { 
    return a == b;
}

template<>
bool isEqual< float OR double OR long double >( T a, T b ) { 
    return abs( a - b ) < epsilon;
}

【问题讨论】:

标签: c++ templates


【解决方案1】:

对于 C++11,可以使用 type traits。请参阅std::enable_if 文档 在您的情况下,它可能如下所示:

函数参数特化:

template<class T>
bool isEqual(T a, T b, typename std::enable_if<std::is_integral<T>::value >::type* = 0) 
{
    return a == b;
}

template<class T>
bool isEqual(T a, T b, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0) 
{
    return abs( a - b ) < epsilon;
}

返回类型特化:

template<class T>
typename std::enable_if<std::is_integral<T>::value, bool >::type isEqual(T a, T b)

{
    return a == b;
}

template<class T>
typename std::enable_if<std::is_floating_point<T>::value, bool >::type isEqual(T a, T b)
{
    return abs( a - b ) < epsilon;
}

【讨论】:

  • 或者,在返回类型上使用enable_if,就像在 cppreference 上一样(这可以防止任何误用),或者作为带有默认参数的附加模板参数(仅在显式指定模板参数时才误用)。
  • @DyP 谢谢,我添加了另一种可能性
【解决方案2】:

是的,您可以将 SFINAE 与来自&lt;type_traits&gt; 的元函数结合使用

#include<type_traits>

template<class IntegralType>
typename std::enable_if<
    std::is_integral<IntegralType>::value,
    bool>::type

isEqual(IntegralType a,IntegralType b)
{
    return a == b;
}

template<class FloatingType>
typename std::enable_if<
    std::is_floating_point<FloatingType>::value,
    bool>::type

isEqual(FloatingType a,FloatingType b)
{
    return fabs(a-b) <  std::numeric_limits<FloatingType>::epsilon();
}

【讨论】:

    【解决方案3】:

    你可以专攻&lt;type_traits&gt;

    然后你可以根据类别对功能进行分组

    template<typename T, bool INTEGRAL> class isEqualbyType;
    
    template<typename T>
    class isEqualbyType<T, true>
    {
    public:
        static bool cmp( T a, T b ) { 
            return a == b; }
    };
    
    template<typename T>
    class isEqualbyType<T, false>
    {
    public:
    
        static bool cmp( T a, T b ) {
            static const double epsilon=1e-50;
            return abs( a - b ) < epsilon; }
    };
    
    template<typename T>
    bool isEqual( T a, T b )
    {
       return isEqualbyType<T, std::is_integral<T>::value>::cmp(a,b);
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-25
      • 2018-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多