https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119469
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The bug is because I implemented the result of ranges::iter_move in terms of
remove_reference_t<decltype(*E)>&& because that's what I assume the type of
std::move(*E) to be.
But when E is a function reference, *E first decays it to a pointer, then
dereferences the pointer, and gives you back the original function reference.
What I don't understand is why the type of std::move(*E) is not the return type
of std::move(*E)!
template<typename _Tp, typename _Up = _Tp&&>
_Up
__declval(int);
template<typename _Tp>
_Tp
__declval(long);
template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));
template<typename T> struct remove_reference { using type = T; };
template<typename T> struct remove_reference<T&> { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
template<typename T> using remove_reference_t = typename
remove_reference<T>::type;
template<typename T>
remove_reference_t<T>&& move(T&& t) { return
static_cast<remove_reference_t<T>&&>(t); }
template<typename, typename> constexpr bool is_same_v = false;
template<typename T> constexpr bool is_same_v<T,T> = true;
template<typename T, typename U> concept same_as = is_same_v<T,U>;
using F = int();
static_assert( same_as<decltype(*declval<F&>()), F&> );
// This fails:
// static_assert( same_as<decltype(move(*declval<F&>())),
remove_reference_t<F&>&&> );
// Because:
static_assert( same_as<decltype(move(*declval<F&>())), F&> );
static_assert( same_as<remove_reference_t<F&>&&, F&&> );
I don't understand why the return type of move<F&> is not F&&