https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119469
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> --- We define iter_rvalue_reference_t<F&> in terms of remove_reference_t<F&>&& instead of decltype(std::move(*std::declval<F&>())) and they're not the same. But I don't understand why. This fixes iter_rvalue_reference_t (and a comment typo): --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -133,12 +133,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __result<_Tp> { using type = decltype(iter_move(std::declval<_Tp>())); }; - // Otherwise, if *E if an lvalue, use std::move(*E). + // Otherwise, if *E is an lvalue, use std::move(*E). template<typename _Tp> requires (!__adl_imove<_Tp>) && is_lvalue_reference_v<__iter_ref_t<_Tp>> struct __result<_Tp> - { using type = remove_reference_t<__iter_ref_t<_Tp>>&&; }; + { using type = decltype(std::move(*std::declval<_Tp>())); }; template<typename _Tp> static constexpr bool But I'd like to understand why the original code wasn't equivalent.