Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow implicit cast operator for const reference only

Tags:

c++

Is there a way to make a custom cast operator only available (or only implicit) if the object is const?

Example:

class Foo;
class Bar;

class MyClass {
    public:
        operator Foo() const;
        operator Foo() = delete; // this doesn't seem to have any effect
        // I also tried explicit operator Foo(); - no change
        operator Bar();
};

As you can see, I'd like MyClass to be implicitly cast to Foo if it is const, but to Bar if it is not const. This is because a pair of overloaded functions exists:

void f(Foo x);
void f(Bar x);

And I'd like to be able to pass MyClass to f, so that the correct function is selected depending on whether it is const or not. This way however, I am getting an ambiguous call to overloaded function. Why?

int main() {
    f(MyClass());
}

Important: I know that I can make this work easily by turning the cast operators into constructors, but unfortunately, Foo, Bar, and f cannot be modified. For context, this is an idea to solve my other problem: Is there a way to resolve this ambiguous implicit cast operator overload?

like image 993
Detheroc Avatar asked Dec 26 '21 20:12

Detheroc


1 Answers

The best viable overload is chosen before its access and/or removal is checked. As there is no best viable overload with the original class definition it doesn't even get to that stage. That is, the ambiguity needs to be resolved for the overload resolution already.

Making one of the two conversion operators explicit does resolve the issue (with the test program there are still errors due to Bar being incomplete). Using a combination of explicit (and = deleteed although that is optional) conversions does yield a version which may be what is looked for:

#include <iostream>
class Foo {};
class Bar {};

class MyClass {
    public:
        explicit operator Foo() const& = delete;
        explicit operator Foo() && = delete;
        operator Foo()& { return Foo(); }

        explicit operator Bar() const& = delete;
        operator Bar() && { return Bar(); }
        explicit operator Bar() & = delete;;
};

void f(Foo) { std::cout << "f(Foo)\n"; }
void f(Bar) { std::cout << "f(Bar)\n"; }

int main() {
    f(MyClass());
    MyClass x;
    f(x);
}

I didn't manage to create a version also accepting MyClass const y; f(y);: making the const& conversion operator non-explicit (for either conversion) causes an ambiguity elsewhere.

like image 97
Dietmar Kühl Avatar answered Sep 18 '22 14:09

Dietmar Kühl