It seems that if I have a conversion operator to a reference, this operator will take precedence over a conversion to a bool
. Why does this happen, and how can I fix it?
(If it matters, I am using GCC 4.5. I verified on ideone that the same behavior is found with GCC-4.7.2.)
Assume the following:
class B {
protected:
const int a_;
int b_;
B (int b, int a) : a_(a), b_(b) {}
public:
operator bool () const { return b_ == a_; }
};
class D1 : public B {
public:
D1 (int b = 0, int a = 0) : B(b, a) {}
operator int () const { return b_; }
};
class D2 : public B {
public:
D2 (int b = 0, int a = 0) : B(b, a) {}
operator int & () { return b_; }
};
Then, assume they are used in a simple program like this:
int main () {
if (D1 d1a = D1('a', 'a')) std::cout << "d1a\n";
if (D1 d1b = D1('b', 'a')) std::cout << "d1b\n";
if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n";
if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n";
return 0;
}
The output of this program is:
d1a
d2a
d2b
Note that d1b
is not in the output, which means the conversion to bool
worked the way I expected it to for D1
. But, for D2
, it seems the conversion to the reference type took precedence over the bool
conversion. Why did this happen? Is there a simple change I can make to D2
to allow the bool
conversion to take precedence in the if
check?
Currently, I am using D1
and adding an assignment operator to it to achieve the behavior of a reference.
Actually, it has nothing to do with int&
, it's a matter of const
-ness:
operator bool () const { return b_ == a_; }
/* ^^^^^ */
/* vvvvv */
operator int & () { return b_; }
d2a
is a D2
, not a const D2
, so the non-const conversion operator is a better fit. If you write it as
operator const int & () const { return b_; }
you will get the expected behaviour, see http://ideone.com/vPPPYV.
Note that operator const int&
won't interfere even if you use the const
versions of your objects, the following lines would still result in your expected behaviour (see http://ideone.com/DTE0xH):
if (const D1 d1a = D1('a', 'a')) std::cout << "d1a\n";
if (const D1 d1b = D1('b', 'a')) std::cout << "d1b\n";
if (const D2 d2a = D2('a', 'a')) std::cout << "d2a\n";
if (const D2 d2b = D2('b', 'a')) std::cout << "d2b\n";
This
D1 d1a = D1('a', 'a');
D1 d1b = D1('b', 'a');
D2 d2a = D2('a', 'a');
D2 d2b = D2('b', 'a');
if (d1a) std::cout << "d1a\n";
if (d1b) std::cout << "d1b\n";
if (d2a) std::cout << "d2a\n";
if (d2b) std::cout << "d2b\n";
prints
d1a d2a
for me.
You have
if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n";
if (D2 d2a = D2('b', 'a')) std::cout << "d2b\n";
What happens if you don't use the same name in both cases?
There's only d1a
and d2a
in the output if I replace the 4th if by
if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n";
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