Mic*_*ndr 3 c++ comparison templates floating-accuracy
在模板类中执行==和!=运算符的正确方法是什么?假设这段代码:
template<typename T>
class C {
T x, y;
public:
C(T a, T b) : x(a), y(b) {}
bool cmp() {
return x == y;
}
};
int main()
{
// OK
C<int> i(1,2);
i.cmp();
// not OK
C<double> d(1.0, 2.0);
d.cmp();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你用g ++ -Wfloat-equal构建它,你就会得到
警告:将浮点数与==或!=进行比较是不安全的[-Wfloat-equal]
因为你不能简单地比较浮点变量.
我已经使用type_traits和enable_if解决了这个问题(感谢@Andrew和@OMGtechy):
#include <type_traits>
#include <limits>
#include <cmath>
#include <iostream>
using namespace std;
template <typename IntegralType>
typename std::enable_if<std::is_integral<IntegralType>::value, bool>::type
equal(const IntegralType& a, const IntegralType& b) {
return a == b;
}
template <typename FloatingType>
typename std::enable_if<std::is_floating_point<FloatingType>::value, bool>::type
equal(const FloatingType& a, const FloatingType& b) {
return std::fabs(a-b) < std::numeric_limits<FloatingType>::epsilon();
}
template<typename T>
class C {
T x, y;
public:
C(T a, T b) : x(a), y(b) {}
bool cmp() {
return equal(x, y);
}
};
int main()
{
// OK
C<int> i(1,2);
cout << i.cmp() << endl;
// not OK
C<double> d(1.0, 1.0);
cout << d.cmp() << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个问题似乎要问两件事:
第二个问题的一个答案是使用类型特征.下面的代码针对您的情况演示了这一点,为一般类型(使用==)提供了comparison_traits,并使用容差(也回答了第一个问题)为双打提供了专门化.
#include <cmath>
template <typename T> struct comparison_traits {
bool equal(const T& a, const T& b) {
return a == b;
}
// etc.
};
template<> struct comparison_traits<double> {
bool equal(const double& a, const double& b) {
return fabs(a - b) < 1e-15; // or whatever...
}
};
template <typename T>
class C {
T x, y;
public:
C(const T& a, const T& b) : x(a), y(b) {}
bool cmp() {
return comparison_traits<T>::equal(x, y);
}
};
int main() {
// OK
C<int> i(1, 2);
i.cmp();
// Now OK too...
C<double> d(1.0, 2.0);
d.cmp();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其他选择包括:
提供允许您指定比较函数的模板参数,默认为std :: equal_to
将您的模板专门用于double,以便您可以编写不同的cmp()实现