c++language-lawyerconversion-operatordirect-initialization

Why does direct initialization use a const lvalue reference qualified conversion function?


I have two classes st and foo:

struct st {
    st() = default;

    st(const st&) {
        std::cout << "copy ctor." << std::endl;
    }

    st(st&&) {
        std::cout << "move ctor." << std::endl;
    }
};

struct foo {
    operator st&() & {
        return s;
    }

    operator const st&() const& {
        return s;
    }

    operator st&&() && {
        return std::move(s);
    }

    operator const st&&() const&& {
        return std::move(s);
    }

    st s;
};

When I run code like this:

st s = st(foo());

It calls the copy constructor of st.

Why does it not call foo's rvalue-reference-qualified conversion function and use st's move constructor?


EDIT:


Solution

  • Calling the copy constructor is wrong. The compiler is not following the specification.

    The call is ill-formed, because overload resolution should be ambiguous.

    The problem is quite generally that if you have two viable overloads, in this case the constructors

    st(const st&);
    

    and

    st(st&&);
    

    and both overloads require a user-defined conversion sequence in the argument where both use a different conversion function or constructor, the two conversion sequences are always considered equally good. How good the standard conversion sequences and the reference binding involved are, is only considered if the two user-defined conversion sequences would use the same conversion operator or constructor.