如何以模板类型名依赖的方式提高C ++模板的精度?

时间:2012-08-08 21:48:06

标签: c++ templates stl

我有一个模板化的数学函数,它接受两个值,对它们进行一些数学运算,并返回相同类型的值。

template <typename T>
T math_function(T a, T b) {
  LongT x = MATH_OP1(a,b);
  return MATH_OP2(x,a);
}

我想将中间值(在x中)存储在一个基本上是T的长版本(上面称为LongT)的类型中。所以,如果T是浮点数,我希望x是双精度数;如果T是一个int,我希望x是一个long int。

有没有办法实现这个目标?我试过enable_if,但似乎我真的需要一个enable_if_else

我更愿意让编译器自己弄清楚LongT的用途。当我调用函数时,我宁愿不必指定它。

5 个答案:

答案 0 :(得分:5)

您可以定义将生成所需类型的类型映射:

template <typename T> struct long_type;
template <> struct long_type<int> {
   typedef long type;
};
template <> struct long_type<float> {
   typedef double type;
};

然后使用该元函数:

template <typename T>
T math_function(T a, T b) {
  typename long_type<T>::type x = MATH_OP1(a,b);
  return static_cast<T>(MATH_OP2(x,a));
}

使用此特定实现,您的模板将无法针对您提供long_type特征的类型以外的任何类型进行编译。您可能希望提供仅映射到自身的通用版本,以便在输入为long long int时使用(假设您的架构中没有更大的类型)。

答案 1 :(得分:5)

假设您不需要处理T=long,只需为intfloat创建特征:

template <typename T>
struct LongT;

template <>
struct LongT<int>
{
    typedef long value_type;
};

template <>
struct LongT<float>
{
    typedef double value_type;
};

template <typename T>
T math_function(T a, T b) {
  typename LongT<T>::value_type x = MATH_OP1(a,b);
  return MATH_OP2(x,a);
}

答案 2 :(得分:3)

在C ++ 11中,您可以使用auto关键字来检索MATH_OP的类型。它是安全的,由编译器处理。

auto x = MATH_OP1(a,b);

答案 3 :(得分:1)

template<typename T> struct LongT  {typedef T type;}

template<> struct LongT<int8_t>    {typedef int16_t type;}
template<> struct LongT<int16_t>   {typedef int32_t type;}
template<> struct LongT<int32_t>   {typedef int64_t type;}
template<> struct LongT<int64_t>   {typedef intmax_t type;}
// same for unsigned ...

template<> struct LongT<float>     {typedef double type;}
// template<> struct LongT<double> {typedef long double type;}

像这样使用:

typename LongT<T>::type  x;

答案 4 :(得分:0)

您可以编写自己的结构专有名称,或使用类似

的内容
#include <type_traits>

template<typename T>
void func(const T& f, const T& s)
{
   typename std::conditional
   <
      std::is_same<T, float>::value,
      double,
      typename std::conditional
      <
        std::is_same<T, int>::value,
        long,
        void
      >::type
   >::type X(f + s);
   (void)X;
}

int main()
{
   func(1, 1);
   func(1.0f, 1.0f);
   func(1.0, 1.0);
}

http://liveworkspace.org/code/8f75236b880a3fe210a8751e485a47ed

但是写下你自己的专业,建议大卫或马克非常聪明。