diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index a201e24d2e2..e36556dc512 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -133,12 +133,19 @@ _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 requires (!__adl_imove<_Tp>) && is_lvalue_reference_v<__iter_ref_t<_Tp>> struct __result<_Tp> - { using type = remove_reference_t<__iter_ref_t<_Tp>>&&; }; + { + // Instead of decltype(std::move(*E)) we define the type as the + // return type of std::move, i.e. remove_reference_t&&. + // N.B. the use of decltype(declval()) instead of just X&& is + // needed for function reference types, see PR libstdc++/119469. + using type + = decltype(std::declval>>()); + }; template static constexpr bool diff --git a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc index 341bd5b98d7..87375746dfd 100644 --- a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc +++ b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc @@ -157,9 +157,20 @@ test_pr106612() static_assert( std::same_as ); } +void +test_pr119469() +{ + // rvalue references to function types are weird. + using F = int(); + static_assert( std::same_as, F&> ); + static_assert( std::same_as, F&> ); + static_assert( std::same_as, F&> ); +} + int main() { test01(); test_adl(); + test_pr119469(); }