如何创建一个通用的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
无法与fl1
或{{1}混合使用}}。
模板在这里是正确的吗,使用定义顶级fl2
的对象层次结构是否更好?它定义了所有运算符,并为每种支持的类型都有一个子类?虽然我不认为能解决混合类型的问题。
编辑1: 在Barry / lisyarus的背景: 我正在更改一个旧代码库,其类型定义如下:
Num
更改是以尽可能透明的方式在此template<typename a> struct NumT : public SomeSuperType<a> { mp::cpp_int val;};
类型中添加对原始float
和double
类型的支持。
理想情况下,NumT不应该改变,而不是改变decl。类型NumT
。
现有代码只执行val
和a + b
上的其他算术运算,而不是破坏现有的API内容非常重要。
val
答案 0 :(得分:2)
数字类型不同(int
,float
等等)是有原因的,尝试将它们通用可能会出错。尽管如此,您可以使用std::common_type
来推断可以包含两者的类型。
请注意,这里会丢失“precision”。例如,如果您有unsigned long long
1434263462343574573ULL
,请将其转换为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