https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521

Matthijs van Duin <matthijsvanduin at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |matthijsvanduin at gmail dot 
com

--- Comment #3 from Matthijs van Duin <matthijsvanduin at gmail dot com> ---
First off, your example is more complicated than it needs to be. A more minimal
test case would be:

#include <utility>

struct Dest {
        Dest() = default;
        Dest( Dest && ) = default;
        Dest( Dest const & ) = delete;
};

struct Source {
        Dest val;
        operator Dest () && {
                return std::move( val );
        }
        operator Dest const & () const & {
                return val;
        }
};

int main() {
        Source x;
        static_cast<Dest>( std::move( x ) );
}


Second, notice that the two conversions are not really directly comparable
since one converts to directly Dest while the other converts to an expression
used to invoke a constructor of Dest. While it seems desirable for the former
to take preference over the latter, I'm not enough of a language lawyer to be
able to figure out what the C++ standard actually requires overload resolution
to do in this situation.

Replacing
        operator Dest () && {
by
        operator Dest && () && {
fixes the problem, and has the additional benefit of avoiding unnecessary
temporary materialization in situations like:

void foo( Dest && );
int main() {
        Source x;
        foo( std::move( x ) );
}

Reply via email to