I have a wrapper class that should behave like a pointer. I have overloaded operator T*
and operator bool
. Bool does some extra validation.
I tried using the object inside an if, but I notice that operator T*
is called and not bool
. Can someone explain me why? Is this somehow specified in the standard? I tested the sample code below in MSVC, clang and gcc and they all call operator T*
.
Also, from what I read on this page(https://en.cppreference.com/w/cpp/language/implicit_conversion), the if should try to cast to bool
.
#include <stdio.h>
class MyClass
{
public:
MyClass(int i)
: m(i)
{}
operator bool() const
{
printf("operator bool()\n");
return m;
}
operator int* ()
{
printf("operator int* ()\n");
return &m;
}
private:
int m;
};
int main()
{
MyClass a(5);
MyClass b(0);
if (a)
printf("a is true\n");
else
printf("a is false\n");
if (b)
printf("b is true\n");
else
printf("b is false\n");
return 0;
}
PS: I also tried with !!
and (bool)
, but it still calls operator int*()
. For operator bool()
, I have to call it explicitly.
Overloading Binary Operators Suppose that we wish to overload the binary operator == to compare two Point objects. We could do it as a member function or non-member function. To overload as a member function, the declaration is as follows: class Point { public: bool operator==(const Point & rhs) const; // p1.
Operator overloading is one of the best features of C++. By overloading the operators, we can give additional meaning to the operators like +-*/=.,= etc., which by default are supposed to work only on standard data types like int, float, char, void etc. It is an essential concept in C++.
No we cannot overload integer or float types because overloading means to change the working of existing operators or make them to work with objects int is single member not an object.
The = and & C++ operators are overloaded by default. For example, you can copy the objects of the same Class directly using the = operator. Operator precedence doesn't change the associatively and precedence of operators.
In your class definition the conversion operator operator bool
is declared with the qualifier const
but the objects used in the if statements are not constant objects.
operator bool() const
^^^^^
{
printf("operator bool()\n");
return m;
}
Remove the qualifier const
and the operator operator bool
will be called.
Or declare the conversion operator operator int *
like
operator const int* () const
{
printf("operator int* ()\n");
return &m;
}
and again the operator operator bool
will be called.
When an operator has the qualifier const and applied to a non-constant object then one more conversion that is the qualification conversion is required.
Moreover you may declare the operator even as explicit. For example
explicit operator bool()
{
printf("operator bool()\n");
return m;
}
If you want to see how to arrive at Vlad's (correct) answer yourself, the process is roughly
if
statement
The condition is an expression which is contextually convertible to bool
Contextual conversions come under Implicit conversions - note in particular that
If there are multiple overloads of the function or operator being called, after the implicit conversion sequence is built from T1 to each available T2, overload resolution rules decide which overload is compiled.
And then under Order of the conversions, that the third step "zero or one standard conversion sequence" comes after the user-defined conversion, and that this step can convert pointer to bool.
This means that both the user-defined conversion operators are viable for the middle step in that sequence. Finally,
Overload resolution
describes how to select the best viable function. Since both operators are viable within the context of the middle step of the conversion sequence, the extra pointer-to-bool conversion that happens after this doesn't contribute to the overload ranking.
Specifically, the ranking is based on the fact that one operator requires const qualification of its implicit first (this
) parameter, and the other doesn't. This is why a pair of const- and non-const-qualified overloads of the same operator will always choose the overload whose qualification most closely matches the object it's being called on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With