Jump to content
  • Advertisement
Sign in to follow this  
Kest

Ambiguous condition operations

This topic is 4258 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

If I create conversion operators for a class, such as:
operator const float*() const { return FData; }
Then provide a bool or BOOL (int) operator:
operator bool() const { return FData && *FData != 0; }
Then when using the class in a condition such as "if( instance )", the bool operator seems to be the one favored without any compiler complaints. However, if I attempt to use several of the class in the same condition, such as "if( instance_a && instance_b ), I get ambiguous complaints involving the built in && operator. It can't seem to choose between the float* and bool type. Why is it that two together seem to make the operation more complex? And is there any way I can fix the problem without removing one of the conversion operators? Thanks for any help

Share this post


Link to post
Share on other sites
Advertisement
The number of steps needed to transform the values so that operator && can be applied is the same. So the compiler cannot decide which one to use. However you can provide a special version of operator && that expects two instances of your class to provide a better match (without conversion).

Share this post


Link to post
Share on other sites
But wouldn't that only fix the specific situation of using the && operator between two of the class type? After doing so, just adding another type of condition brings the problem back:
if( some_x_ptr != null && class_instance )


Do I need to create two global templated operators instead?

template <typename Type>
BOOL operator && (const MyClass &a,const Type &b) { return a.BoolCondition() && b; }
template <typename Type>
BOOL operator && (const Type &b,const MyClass &a) { return a.BoolCondition() && b; }


Or is there a better way to fix it?

Share this post


Link to post
Share on other sites
Just in case someone gets a strange urge to copy my example operators above, I wanted to point out that I made a horrible mistake by changing the order of parameters (b, a) in the condition for the second example.

It should have been this:

template <typename Type>
BOOL operator && (const MyClass &a,const Type &b) { return a.BoolCondition() && b; }
template <typename Type>
BOOL operator && (const Type &a,const MyClass &b) { return a && b.BoolCondition(); }

Share this post


Link to post
Share on other sites
It's impossible to correctly overload && or || - C++ provides no facilities to allow functions to optionally evaluate parameters, so the short circuit behaviour of &&/|| can#t be replicated in a user defined function.

This is one of the reasons why it's considered very bad practice to provide conversion operators.

Share this post


Link to post
Share on other sites
Never, ever, ever overload &&, || or ->. (I don't think it's possible to overload . but if you can, don't do that either). See Meyers, Effective C++ for the reasons why. But just don't do it. Ever.

Share this post


Link to post
Share on other sites
Guest Deventer
Actually, you shouldn't overload operator&&, operator|| or operator, according to Meyers.

Overloading operator-> should be fine.

Share this post


Link to post
Share on other sites
Quote:
Original post by Deventer
Overloading operator-> should be fine.


Not only that, overloading operator-> is fundamental to the implementation of the entire iterator concept, which the C++ standard library uses extensively.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
... is there any way I can fix the problem without removing one of the conversion operators?


No. Here's a word of wisdom: avoid conversion operators. Make your conversions explicit. It not only helps the reader understand your code (and that could be you, 6 weeks from now), but it avoids problems even seasoned C++ experts sometimes run into when entangling themselves with the myriad promotion, conversion, and resolution rules.

You will notice that the C++ standard library does not make use of conversion operators, except for IOStreams, and those are mostly to avoid breaking existing pre-standard code.

Share this post


Link to post
Share on other sites
Quote:
is there any way I can fix the problem without removing one of the conversion operators?

Give the compiler a helping hand.
Quote:

if( (bool)instance_a && (bool)instance_b )


Also consider what others in this thread have wrote, is there any benifit from having a bool operator(one I might add that is floored) instead of a valid function?

Herb Sutter:
Quote:

Implicit conversions can interfere with overload resolution.

Implicit conversions can silently let "wrong" code compile cleanly.

Avoid writing conversion operators. Avoid non-explicit constructors.


Anyway back to your bool operator
Quote:
operator bool() const { return FData && *FData != 0; }

FData is a pointer to float and you are comparing it to an int, not problem there the int gets promoted to a float. But when will !*FData != 0" ever be true?


[Edited by - CmpDev on April 22, 2007 1:52:54 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!