https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92662
--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Michael Matz from comment #4) > the return value of moveme() has type Test&&. There exists a conversion > operator exactly matching that type, See Bug 86521 comment 4, it's similar here. Before choosing which conversion operator to use, the compiler considers the constructors of S, finding S(const S&) and S(S&&) as candidates. There is a viable conversion from Test&& to const S& and also one from Test&& to S&&. Both of those conversion sequences have conversion rank "user-defined" (because they use a user-defined conversion operator) but they use different conversion operators. Two different user-defined conversions are ambiguous, it doesn't matter that one is a better match for being called on an rvalue. The moveme(t).str() case is different, because there's no user-defined conversion. Overload resolution chooses which str() to call, and that *does* consider the ref-qualifiers when deciding which str() is a better match.