libstdc++: Fix std::ranges::iter_move for function references [PR119469]
The result of std::move (or a cast to an rvalue reference) on a function reference is always an lvalue. Because std::ranges::iter_move was using the type std::remove_reference_t<X>&& as the result of std::move, it was giving the wrong type for function references. Use a decltype-specifier with declval<remove_reference_t<X>>() instead of just using the remove_reference_t<X>&& type directly. This gives the right result, while still avoiding the cost of doing overload resolution for std::move. libstdc++-v3/ChangeLog: PR libstdc++/119469 * include/bits/iterator_concepts.h (_IterMove::__result): Use decltype-specifier instead of an explicit type. * testsuite/24_iterators/customization_points/iter_move.cc: Check results for function references. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
parent
b631ff45f2
commit
3e52eb28c5
2 changed files with 20 additions and 2 deletions
|
@ -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<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>>&&; };
|
||||
{
|
||||
// Instead of decltype(std::move(*E)) we define the type as the
|
||||
// return type of std::move, i.e. remove_reference_t<iter_ref>&&.
|
||||
// N.B. the use of decltype(declval<X>()) instead of just X&& is
|
||||
// needed for function reference types, see PR libstdc++/119469.
|
||||
using type
|
||||
= decltype(std::declval<remove_reference_t<__iter_ref_t<_Tp>>>());
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
|
|
|
@ -157,9 +157,20 @@ test_pr106612()
|
|||
static_assert( std::same_as<decltype(std::ranges::iter_move(I3{})), F> );
|
||||
}
|
||||
|
||||
void
|
||||
test_pr119469()
|
||||
{
|
||||
// rvalue references to function types are weird.
|
||||
using F = int();
|
||||
static_assert( std::same_as<std::iter_rvalue_reference_t<F>, F&> );
|
||||
static_assert( std::same_as<std::iter_rvalue_reference_t<F&>, F&> );
|
||||
static_assert( std::same_as<std::iter_rvalue_reference_t<F&&>, F&> );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test_adl();
|
||||
test_pr119469();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue