【问题标题】:Generic Num class通用数字类
【发布时间】:2016-12-12 03:18:36
【问题描述】:

您如何创建一个通用的类 num 以便唯一重要的是相关的成员函数/运算符存在?

我已经阅读了SFINAE,但说实话我不明白。

#include <iostream>

template<typename T>
class Numeric {
  const T a;
public:
  Numeric(const T &v) : a(v) {}

  T operator+(const Numeric<T> &b) {
    return a + b.a;
  }
};

int main() {
  Numeric<float> fl1(35.5);
  Numeric<float> fl2(10.5);
  Numeric<uint64_t> i64(10000);
  std::cout << (i64 + fl1 + fl2) << std::endl;
  return 0;
}

在这里,fl1 + fl2 可以,但由于运算符定义表明 T 是同一类型,i64 不能与 fl1fl2 混合使用。 模板在这里是正确的吗,最好使用定义顶级Num 的对象层次结构,例如定义所有运算符并为每种支持的类型都有一个子类?虽然我认为这不能解决混合类型问题。

编辑 1: Barry/lisyarus 的背景资料: 我正在更改一个旧代码库,它的类型定义如下:

template<typename a> struct NumT : public SomeSuperType<a> { mp::cpp_int val;};

更改是在此NumT 类型中以尽可能透明的方式添加对本机floatdouble 类型的支持。 理想情况下,NumT 除了更改 decl 之外不应更改。 val 的类型。 现有代码只对a + bval 进行其他算术运算,不破坏现有API 内容很重要。 i64 + fl1 + fl2 == 10046

【问题讨论】:

  • Numeric&lt;T&gt; 尝试解决的问题可能是 T 无法解决的问题?
  • 您到底想达到什么目的?或者,i64 + fl1 + fl2 的类型应该是什么?不管是int64还是float,都是有损的。

标签: c++ c++11


【解决方案1】:

数字类型不同(intfloat 等)是有原因的,试图将它们通用化可能会出错。尽管如此,您可以使用std::common_type 来推断可以包含两者的类型。

请注意,这里会丢失 "precision"。例如,如果您有 1434263462343574573ULLunsigned long long,将其转换为 double 会丢失一些有效数字.

#include <iostream>
#include <type_traits>

template<typename T>
class Numeric {
    const T a;
public:
    Numeric(const T &v) : a(v) {}
    T get() const { return a; }
};

template<typename T, typename U>
Numeric<typename std::common_type<T, U>::type> //With C++14, do std::common_type_t<T, U>
operator + (const Numeric<T>& a, const Numeric<U>& b) {
    return a.get() + b.get();   //Works because of the converting constructor
}

template<typename T>
std::ostream& operator << (std::ostream& os, const Numeric<T>& n){
    os << n.get();
    return os;
}

int main() {
    Numeric<float> fl1(35.5);
    Numeric<float> fl2(10.5);
    Numeric<uint64_t> i64(10000);
    std::cout << (i64 + fl1 + fl2) << std::endl;
    return 0;
}

打印出来:

10046

【讨论】:

  • 我明白了,很好。我不知道std::common_type。我会警惕精度问题
  • “数字类型存在于类中是有原因的”这是什么意思?
  • @LightnessRacesinOrbit 我的意思是我们有不同的数字类型是有原因的,例如intfloat 等...我现在改写了声明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2022-01-03
  • 2013-01-04
  • 2010-11-21
  • 2012-04-06
  • 1970-01-01
相关资源
最近更新 更多