如何为基本类型(浮点型)编写替换,以覆盖 运算符 == C++
How to write a drop-in replacements for fundamental type (float) that override operator== in C++?
我们不能直接比较二进制浮点数。我正在为浮点数编写一个插入式替换类覆盖 bulti-in 比较运算符:
template<class U>
class Float {
private:
U val;
public:
Float(U v = 0): val(v) {}
operator U() const { return val; }
friend bool operator<(Float a, Float b) { return a.val + 1e-6 < b.val; }
friend bool operator==(Float a, Float b) { return !(a < b) && !(b < a); }
friend Float operator*(Float a, Float b) { return a.val * b.val; }
template<class T>
friend Float operator*(T a, Float b) { return a * b.val; }
template<class T>
friend Float operator*(Float a, T b) { return a.val * b; }
};
现在我们可以写这样的东西:
#include<assert.h>
int main() {
Float<double> a = 0.2, b = 0.02;
assert(a * a == 2 * b);
}
但是,此代码将显示意外行为:
#include<complex>
int main() {
std::complex< Float<double> > a(0.2);
a * 2.0;
}
它会一次又一次地呼唤Float::operator*(std::complex<Float<double> >, Float)
就像一个递归的无限循环,最后得到堆栈溢出。如何解决这个问题?
编辑
DeadMG和Charles Bailey指出,来自ISO/IEC 14882:2011,26.4:"实例化除浮点数,双精度或长双精度以外的任何类型的模板复合体的效果未指定。
也许我举了一个错误的反例。我们仍然可以讨论如何为基本类型编写一个好的替换类。
让我澄清我的动机,assert(0.1 * 0.1 == 0.01);
违反直觉。这就是为什么我写了一个 Float 类,它使用"几乎相等"的行为来比较两个浮点数。
使构造函数显式。
a * 2.0;
隐式构造一个浮点型,然后调用:
template<class T>
friend Float operator*(T a, Float b)
{
return a * b.val;
}
这反过来又在 b.val 上调用 * 运算符时隐式构造另一个 Float; 然后你从那里递归。
在我提出完全修复之前,您需要进一步充实您的预期行为。
我用来探索它并测试修复的代码:
#include <iostream>
template<class U>
class Float {
private:
U val;
public:
explicit Float(U v = 0): val(v)
{
std::cout << "constructor ";
}
operator U() const { return val; }
friend bool operator<(Float a, Float b) { return a.val + 1e-6 < b.val; }
friend bool operator==(Float a, Float b) { return !(a < b) && !(b < a); }
friend Float operator*(Float a, Float b) { return a.val * b.val; }
template<class T>
friend Float operator*(T a, Float b)
{
std::cout << "here";
return a * b.val;
}
template<class T>
friend Float operator*(Float a, T b) { return a.val * b; }
};
#include<complex>
int main() {
std::complex< Float<double> > a(0.2);
a * 2.0;
}
相关文章:
- 模板参数替换失败,并且未完成隐式转换
- 如何用转义符替换字符串中的所有特殊字符
- 使用ios:ate写入到流会覆盖现有文件
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 我可以重新分配/覆盖std::字符串吗
- 在一个读写器队列中,我可以用volatile替换原子吗
- 用符号版本替换对函数的所有调用
- 叮叮当当在修复时插入多个"覆盖"说明符
- 谷歌模拟和覆盖关键字
- 如何通过替换顺序代码的while循环来添加OpenMP for循环
- 替换基于地图的所有引用
- 按平均值替换数组中的元素
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 使用子类覆盖基类中定义的函数
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 调用Main将替换矢量对象并覆盖数据
- 如何为基本类型(浮点型)编写替换,以覆盖 运算符 == C++