I've been playing with C++ recently, and I just stumbled upon an interesting precedence issue. I have one class with two operators: "cast to double" and "+". Like so:
class Weight {
double value_;
public:
explicit Weight(double value) : value_(value) {}
operator double() const { return value_; }
Weight operator+(const Weight& other) { return Weight(value_ + other.value_); }
};
When I try to add two instances of this class...
class Weighted {
Weight weight_;
public:
Weighted(const Weight& weight) : weight_(weight) {}
virtual Weighted twice() const {
Weight w = weight_ + weight_;
return Weighted(w);
}
};
...something unexpected happens: the compiler sees the "+" sign and casts the two weight_
s to double
. It then spits out a compilation error, because it can't implicitly cast the resulting double back to a Weight
object, due to my explicit
one-argument constructor.
The question: how can I tell the compiler to use my own Weight::operator+
to add the two objects, and to ignore the cast operator for this expression? Preferably without calling weight_.operator+(weight_)
, which defeats the purpose.
Update: Many thanks to chris for pointing out that the compiler is right not to use my class's operator+
because that operator is not const
and the objects that are being +
ed are const
.
I now know of three ways to fix the above in VS2012. Do see the accepted answer from chris for additional information.
- Add the
explicit
qualifier toWeight::operator double()
. This doesn't work in VS 2012 (no support), but it stands to reason that it's a good solution for compilers that do accept this approach (from the accepted answer). - Remove the
virtual
qualifier from methodWeighted::twice
, but don't ask me why this works in VS. - Add the
const
qualifier to methodWeight::operator+
(from the accepted answer).