5
votes

In C++, I'm trying to use implicit conversion with a conditional operator. Consider this example:

class MyFloat
{ 
    public:                                                                    
        MyFloat(float val){m_val = val;}
        operator float(){return m_val;}
    protected:
        float m_val;
};

int main(int argc, char **argv)
{
    MyFloat a = 0.5f;
    MyFloat b = 1.0f;                            
    float x = true ? a-0.5f : b;
    return 0;
}

It causes a compiler error:

error: operands to ?: have different types ‘MyFloat’ and ‘float’

I expect the conditional operator to implicitly convert b to the type of a-0.5, float. But this does not happen. How do I achieve this implicit cast?

Ideally, I want to avoid a static cast or an accessor method like float MyFloat::getValue().

3
You started out well, with "implicit conversion", then lost it with "implicit cast". A cast is something you write in your source code to tell the compiler to do a conversion. There is no such thing as an implicit cast. - Pete Becker
I just tried to compile and run your code in MS Visual Studio 2012 Professional. 0 Errors, 0 Warnings, works good. - LihO
@LihO, it fails in GCC: ideone.com/9WPniF - Mark Ransom
If you must define an implicit conversion, it can still be useful to define a member function that does exactly the same thing, for cases like this, passing through ..., etc. Adding a float MyFloat::getValue() const would not make your interface any worse than it already is: it's adding a way for someone to get a float by saying exactly what they're doing, when you already gave the ability to get a float without even meaning to. - aschepler

3 Answers

8
votes

The problem is that there are two conversions. The compiler can convert a-0.5 to MyFloat or it can convert b to float. As long as you have both conversions and neither is marked explicit you'll get this kind of ambiguity all the time.

1
votes

Only some conversions are done for you. From http://msdn.microsoft.com/en-us/library/e4213hs1(v=vs.71).aspx

The first operand must be of integral or pointer type. The following rules apply to the second and third expressions:

  • If both expressions are of the same type, the result is of that type.
  • If both expressions are of arithmetic or enumeration types, the usual arithmetic - conversions (covered in Arithmetic Conversions) are performed to convert them to a common type.
  • If both expressions are of pointer types or if one is a pointer type and the other is a constant expression that evaluates to 0, pointer conversions are performed to convert them to a common type.
  • If both expressions are of reference types, reference conversions are performed to convert them to a common type.
  • If both expressions are of type void, the common type is type void.
  • If both expressions are of a given class type, the common type is that class type.
0
votes

The ternary operator doesn't do any implicit casting if I remember correctly. You will need to either write

static_cast<MyFloat>(a-0.5) 

or

static_cast<float>(b). 

I'll dig through the C++ standards doc when I get home for more details.