#include <cassert>
template<typename T>
struct Exactly : T
{
explicit Exactly(T const& value) : T(value) {}
};
class Complex
{
double re;
double im;
public:
Complex(double re, double im) : re(re), im(im) {}
// Non-members require either friend access or public getters.
double real() const { return re; }
double imag() const { return im; }
};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
bool operator == (Complex const& a, Exactly<Complex> const& b)
{
return (a.real() == b.real()) && (a.imag() == b.imag());
}
// two more overloads for completeness
bool operator == (Exactly<Complex> const& a, Complex const& b)
{
return (a.real() == b.real()) && (a.imag() == b.imag());
}
bool operator == (Exactly<Complex> const& a, Exactly<Complex> const& b)
{
return (a.real() == b.real()) && (a.imag() == b.imag());
}
#pragma GCC diagnostic pop
Exactly<Complex> exactlyOne(Complex(1.0, 0.0));
template<typename T>
Exactly<T> exactly(T const& value)
{
return Exactly<T>(value);
}
int main()
{
Complex c(1.0, 0.0);
// assert( c == c ); // error (no match):
assert( c == exactlyOne );
assert( exactly(Complex(1.0, 0.0)) == c );
assert( exactlyOne == exactlyOne );
}
I2luY2x1ZGUgPGNhc3NlcnQ+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgRXhhY3RseSA6IFQKewogICAgZXhwbGljaXQgRXhhY3RseShUIGNvbnN0JiB2YWx1ZSkgOiBUKHZhbHVlKSB7fQp9OwoKY2xhc3MgQ29tcGxleAp7CiAgICBkb3VibGUgcmU7CiAgICBkb3VibGUgaW07CgpwdWJsaWM6CiAgICBDb21wbGV4KGRvdWJsZSByZSwgZG91YmxlIGltKSA6IHJlKHJlKSwgaW0oaW0pIHt9CgogICAgLy8gTm9uLW1lbWJlcnMgcmVxdWlyZSBlaXRoZXIgZnJpZW5kIGFjY2VzcyBvciBwdWJsaWMgZ2V0dGVycy4KICAgIGRvdWJsZSByZWFsKCkgY29uc3QgeyByZXR1cm4gcmU7IH0KICAgIGRvdWJsZSBpbWFnKCkgY29uc3QgeyByZXR1cm4gaW07IH0KfTsKCiNwcmFnbWEgR0NDIGRpYWdub3N0aWMgcHVzaAojcHJhZ21hIEdDQyBkaWFnbm9zdGljIGlnbm9yZWQgIi1XZmxvYXQtZXF1YWwiCmJvb2wgb3BlcmF0b3IgPT0gKENvbXBsZXggY29uc3QmIGEsIEV4YWN0bHk8Q29tcGxleD4gY29uc3QmIGIpCnsKICAgIHJldHVybiAoYS5yZWFsKCkgPT0gYi5yZWFsKCkpICYmIChhLmltYWcoKSA9PSBiLmltYWcoKSk7Cn0KLy8gdHdvIG1vcmUgb3ZlcmxvYWRzIGZvciBjb21wbGV0ZW5lc3MKYm9vbCBvcGVyYXRvciA9PSAoRXhhY3RseTxDb21wbGV4PiBjb25zdCYgYSwgQ29tcGxleCBjb25zdCYgYikKewogICAgcmV0dXJuIChhLnJlYWwoKSA9PSBiLnJlYWwoKSkgJiYgKGEuaW1hZygpID09IGIuaW1hZygpKTsKfQpib29sIG9wZXJhdG9yID09IChFeGFjdGx5PENvbXBsZXg+IGNvbnN0JiBhLCBFeGFjdGx5PENvbXBsZXg+IGNvbnN0JiBiKQp7CiAgICByZXR1cm4gKGEucmVhbCgpID09IGIucmVhbCgpKSAmJiAoYS5pbWFnKCkgPT0gYi5pbWFnKCkpOwp9CiNwcmFnbWEgR0NDIGRpYWdub3N0aWMgcG9wCgpFeGFjdGx5PENvbXBsZXg+IGV4YWN0bHlPbmUoQ29tcGxleCgxLjAsIDAuMCkpOwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KRXhhY3RseTxUPiBleGFjdGx5KFQgY29uc3QmIHZhbHVlKQp7CiAgICByZXR1cm4gRXhhY3RseTxUPih2YWx1ZSk7Cn0KCmludCBtYWluKCkKewogICAgQ29tcGxleCBjKDEuMCwgMC4wKTsKICAgIC8vIGFzc2VydCggYyA9PSBjICk7IC8vIGVycm9yIChubyBtYXRjaCk6CiAgICBhc3NlcnQoIGMgPT0gZXhhY3RseU9uZSApOwogICAgYXNzZXJ0KCBleGFjdGx5KENvbXBsZXgoMS4wLCAwLjApKSA9PSBjICk7CiAgICBhc3NlcnQoIGV4YWN0bHlPbmUgPT0gZXhhY3RseU9uZSApOwp9