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

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The return type of std::move is an rvalue reference type, but the
std::move(fun) expression produces an lvalue (because the standard says so).

So although the return type of std::move(fun) is int(&&)(int), what you get is
an lvalue and so decltype(std::move(fun)) is int(&)(int). Even though that's
not the return type.

So we can still avoid the cost of doing overload resolution for std::move(*E)
like so:

            using __lval = __iter_ref_t<_Tp>;
            using __rval = remove_reference_t<__lval>&&;
            //  N.B. this is not just __rval, because casting to an rvalue
            //  reference to function type produces an lvalue not an rvalue.
            // C++23 [expr.static.cast]/1, [expr.type.conv]/1 etc.
            using type = decltype(static_cast<__rval>(std::declval<__lval>()));

Because this uses decltype(static_cast<__rval>(*E)) it gives us the right
answer, where previously we just used __rval which was wrong for the function
reference case.

Reply via email to