How to force GCC to warn about usage of a class function?

Viewed 255

Using GCC 4.8.*, when the warning -Wfloat-equal is activated, the compiler warns about strict comparisons between floting point number, like in the following example:

double x = 3.14159;
double y = 1.11111;
if(x == y) // <-- this induces a warning
{ /* ... */ }

Now, imagine I want a class containing double variables and defining the equality operator:

class Complex // (it's only an example)
{
  private:
    double re;
    double im;
  public:
    bool operator == (Complex const& z) const;
};
bool Complex::operator == (Complex const& z) const
{
  return (this->re == z.re) && (this->im == z.im);
}

This does exactly what I expect. Of course, it induces a warning when I compile the class. In order to avoid it (because I understand the warning, thanks to the compiler, but I want to do that, and I don't want to continue to see the warning), I inform the compiler by this way:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
bool Complex::operator == (Complex const& z) const
{
  return (this->re == z.re) && (this->im == z.im);
}
#pragma GCC diagnostic pop

Okay, I don't have the warning when I compile my Complex.cpp file. But it's still dangerous to use the operator == on complex numbers, exaclty like it's dangerous to use operator == on double numbers (it's the reason for the existence of the option -Wfloat-equal). Then, my question:

Is it possible to have a GCC warning (activated by -Wfloat-equal) where the operator == on complex numbers is used ? It's not the existence of the operator I want to warn, but the usage.

Note: I defined the symmetric operator as a class member, but I'm open to have a class function bool equals(...) const called by a bool operator == (Complex const&,Complex const&) if it can simplify my expected behavior.

Note: I don't use C++11 for compatibility reasons.

2 Answers

This seems to work (live on gcc4.8.5):

__attribute__((warning ("your message")))
bool operator == (Complex const& z) const;

of course, you'll need to make sure the offending statement doesn't get optimized out ..

As it is, you'll need to dis/enable it manually (via some define) ... I don't know if gcc allows inspecting if a warning has been enabled or not.

How about using an Exactly wrapper type that expresses the intent clearly?

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

You can then also predefine constants like this (e.g. locally or in a namespace):

Exactly<Complex> exactlyOne(Complex(1.0, 0.0));

And add a "maker" function so that you don't have to repeat the type name such as Complex:

template<typename T>
Exactly<T> exactly(T const& value)
{
    return Exactly<T>(value);
}

operator != left as an exercise to the reader.

Minor update: If you want to allow operator == without Exactly, but with a warning, then you need to add another overload operator ==(Complex const& a, Complex const& b) with the attribute mentioned by Massimiliano Janes. Seems unnecessary though.

Demo

Related