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&&

Reply via email to