Constructor is always used instead of explicit conversion operator

Viewed 930

I have the following class:

template <typename T1>
class Foo {
public:
    Foo(T1* obj) : obj(obj) {}

    template <typename T2>
    Foo(const Foo<T2>& other) : obj(other.obj) {}

    template <typename T2>
    explicit operator Foo<T2>() {
        return Foo<T2>(static_cast<T2*>(obj));
    }
    T1* obj;
};

The intention of the second constructor is that an implicit conversion from Foo<X> to Foo<Y> is allowed iff an implicit conversion from X* to Y* is allowed.

The conversion operator is there to allow an explicit conversion from Foo<X> to Foo<Y> using an explicit conversion from X* to Y*.

But I noticed that the conversion operator never gets used. The compiler always uses the second constructor even when I do an explicit cast. This causes an error if an implicit conversion of the underlying types is not possible.

The following code can be used to test the class above.

class X {};
class Y : public X {};

int main() {
    Y obj;
    Foo<Y> y(&obj);
    Foo<X> x = y; // implicit cast works as expected.
    // y = x; // implicit conversion fails (as expected).
    // y = static_cast<Foo<Y>>(x); // conversion fails because constructor is
                                   // called instead of conversion operator.
}

Is there a way to cause the compiler to use the conversion operator for explicit conversions?

2 Answers
Related