How to write a drop-in replacements for fundamental type (float) that override operator== in C++? -
we can not compare binary floating point directly. writting drop-in replacements class float override bulti-in compare operators::
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 * b.val; } template<class t> friend float operator*(float a, t b) { return a.val * b; } };
now can write this::
#include<assert.h> int main() { float<double> = 0.2, b = 0.02; assert(a * == 2 * b); }
however, code show unexpected behavior::
#include<complex> int main() { std::complex< float<double> > a(0.2); * 2.0; }
it call float::operator*(std::complex<float<double> >, float)
again , again recursive endless loop, , stack overflow. how fix this?
edit
deadmg , charles bailey point out iso/iec 14882:2011, 26.4: "the effect of instantiating template complex type other float, double, or long double unspecified."
maybe have given wrong counter example. still discuss how write drop-in replacements class fundamental type.
let me clear motivation, assert(0.1 * 0.1 == 0.01);
counterintuitive. why write float class used "almost equal" behavior compare 2 floating number.
make constructor explicit.
a * 2.0;
is implicitly constructing float, calling:
template<class t> friend float operator*(t a, float b) { return * b.val; }
which in turn implicitly constructing float when invoke * operator on b.val; , recurse on there.
you need flesh out expected behaviors more before suggest complete fix.
the code used explore & test fix:
#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 * 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); * 2.0; }
Comments
Post a Comment