简体   繁体   English

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

[英]How does one increase precision in C++ templates in a template typename-dependent manner?

I have a templated math function which takes two values, does some math to them, and returns a value of the same type. 我有一个模板化的数学函数,它接受两个值,对它们进行一些数学运算,并返回相同类型的值。

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

I want to store intermediate values (in x) in a type which is basically the long version of T (above, called LongT). 我想将中间值(在x中)存储在一个类型中,该类型基本上是T的长版本(上面称为LongT)。 So, if T is float, I want x to be a double; 所以,如果T是浮点数,我希望x是双精度数; and if T is an int, I want x to be a long int. 如果T是一个int,我希望x是一个long int。

Is there some way to accomplish this? 有没有办法实现这个目标? I tried enable_if , but it seems that I would really need an enable_if_else . 我尝试了enable_if ,但似乎我真的需要一个enable_if_else

I'd prefer to have the compiler figure out what to use for LongT on its own. 我更愿意让编译器自己弄清楚LongT的用途。 I'd rather not have to specify it when I call the function. 当我调用函数时,我宁愿不必指定它。

You can define a type mapping that will yield the needed type: 您可以定义将生成所需类型的类型映射:

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

And then use that metafunction: 然后使用该元函数:

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));
}

With this particular implementation, your template will fail to compile for any type other than the ones for which you have provided the long_type trait. 使用此特定实现,您的模板将无法编译除您提供long_type特征的类型之外的任何类型。 You might want to provide a generic version that will just map to the itself, so that if the input is long long int that is what is used (assuming no larger type in your architecture). 您可能希望提供仅映射到自身的通用版本,以便在输入为long long int使用(假设您的体系结构中没有更大的类型)。

Assuming you don't need to handle T=long for example, just create traits for int and float : 假设您不需要处理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);
}

In C++11 you can use auto keyword to retrieve type of the MATH_OP . 在C ++ 11中,您可以使用auto关键字来检索MATH_OP类型。 It is safe and handled by compiler. 它是安全的,由编译器处理。

auto x = MATH_OP1(a,b);
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;}

Used like so: 像这样使用:

typename LongT<T>::type  x;

You can write your own specialisations of your own structure, or use something like 您可以编写自己的结构,也可以使用类似的结构

#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 http://liveworkspace.org/code/8f75236b880a3fe210a8751e485a47ed

But write your own specializations as suggest David or Mark is pretty clever. 但是建议你自己的专业,因为大卫或马克非常聪明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM