Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting operator always ambiguous

Tags:

c++

casting

Consider the following example:

struct m
{
    m(int ) { }
};

class q
{
public:

    int i;

    q(int i)
    {
        this->i = i;
    }

    operator double()
    {
        return (double) i;
    }

    operator m()
    {
        return (m)i;
    }
};

int main()
{
    q x(1);
    (m)x; // error: ambiguous
}

It fails when I call the casting: ambiguous conversion from q to m. Why so? I really don't get it. I explicitly added a casting operator for m! Why should that be ambiguous? If I remove the cast to double, however, this works. Why does that matter? How can I do what I want to do?

like image 900
Matteo Monti Avatar asked Sep 22 '26 22:09

Matteo Monti


1 Answers

Consider the possible paths that the compiler can take when you do:

m temp__(x);

There are three relevant constructors:

m(int );      // (A)
m(const m& ); // (B)
m(m&& );      // (C)

We could call (A) via x --> double --> int, that is a user-defined conversion sequence.

We could call (B) or (C) via x --> m, that is also a user-defined conversion sequence.

A user-defined conversion sequence can only be preferences to another if they end up calling the same constructor. But in this case, they don't - so there's no way for the compiler to prefer one to the other. Hence, ambiguous.

Your alternatives would be to

  • call your operator directly (or make it a function with some name); or
  • make q inherit from m - the derived-to-base conversion would be preferred to the user-defined conversion sequence; or
  • make both conversion operators explicit - in which case there would only be one viable candidate to begin with, so there would be no ambiguity.
like image 105
Barry Avatar answered Sep 25 '26 11:09

Barry