Why this ref-qualified user defined convertion is called?

Viewed 52

within following small code:

class A {    
};

class B {
    public:
    operator A() const & {
        return A{};
    }
};

void foo(const A& a) {

}

int main()
{
    B b;
    A a1 = b;
    A a2 = B{}; //<--- here
    foo(b);
    foo(B{}); //<--- here
}

Why the specified lines will not create compile error? My cast operator is lvalue qualified by &, so I imagined that it should not be called for these two lines that object is rvalue.

Any idea why this code compiles without any problem? I noticed that if I remove const from cast operator declaration, these two lines will make error. But I'm not sure how being const-qualified affect call of this ref-qualified method.

1 Answers

Because rvalues could be bound to lvalue-reference to const too. (They can't be bound to lvalue-reference to non-const.)

As the workaround, depending on your intent, you can remove the const qualifier as you said, or add overloading with rvalue-reference qualifier (and const qualifier if necessary as @HolyBlackCat suggested) and mark it as delete explicitly. E.g.

class B {
    public:
    operator A() const & {
        return A{};
    }
    operator A() && = delete;
};
Related