Tested on x86_64-pc-linux-gnu, does this look OK for trunk/14?

-- >8 --

This case was incorrectly failing in C++23 mode even after P2492R2
because the perfect forwarding simplification mechanism assumed bound
arguments are copy-constructible which is no longer necessarily true
after that paper.  It'd be easy enough to fix the mechanism, but in
C++23 mode the mechanism is no longer useful since we can just rely on
deducing 'this' to implement perfect forwarding with a single overload
(and done in r14-7150-gd2cb4693a0b383).  So this patch just disables
the mechanism in C++23 mode so that the generic implementation is always
used.

        PR libstdc++/118413

libstdc++-v3/ChangeLog:

        * include/std/ranges
        (_GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING): New.
        (__closure_has_simple_call_op): Only define in C++20 mode.
        (__closure_has_simple_extra_args): Likewise.
        (_Partial, _Pipe): Likewise, for the "simple" partial
        specializations.
        (*::_S_has_simple_call_op): Likewise.
        (*::_S_has_simple_extra_args): Likewise.
        * testsuite/std/ranges/adaptors/100577.cc: Disable some
        implementation detail checks in C++23 mode.
        * testsuite/std/ranges/adaptors/transform.cc (test09): Also test
        partially applying the move-only function.
---
 libstdc++-v3/include/std/ranges               | 53 +++++++++++++++++++
 .../testsuite/std/ranges/adaptors/100577.cc   |  4 +-
 .../std/ranges/adaptors/transform.cc          |  2 +
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index ad69a94b21f..a2b8748bea6 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1028,6 +1028,16 @@ namespace views::__adaptor
        }
     };
 
+#if __cplusplus <= 202003L
+  // In C++20 mode we simplify perfect forwarding of a range adaptor closure's
+  // bound arguments when possible (according to their types), for sake of 
compile
+  // times and diagnostic quality.  In C++23 mode we instead rely on deducing 
'this'
+  // to idiomatically implement perfect forwarding.  Note that this means the
+  // simplification logic doesn't consider C++23 <ranges> changes such as 
P2492R2.
+# define _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING 1
+#endif
+
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
   // True if the range adaptor closure _Adaptor has a simple operator(), i.e.
   // one that's not overloaded according to constness or value category of the
   // _Adaptor object.
@@ -1039,6 +1049,7 @@ namespace views::__adaptor
   template<typename _Adaptor, typename... _Args>
     concept __adaptor_has_simple_extra_args = 
_Adaptor::_S_has_simple_extra_args
       || _Adaptor::template _S_has_simple_extra_args<_Args...>;
+#endif
 
   // A range adaptor closure that represents partial application of
   // the range adaptor _Adaptor with arguments _Args.
@@ -1139,6 +1150,7 @@ namespace views::__adaptor
 #endif
     };
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
   // Partial specialization of the primary template for the case where the 
extra
   // arguments of the adaptor can always be safely and efficiently forwarded by
   // const reference.  This lets us get away with a single operator() overload,
@@ -1195,6 +1207,7 @@ namespace views::__adaptor
 
       static constexpr bool _S_has_simple_call_op = true;
     };
+#endif // _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
 
   template<typename _Lhs, typename _Rhs, typename _Range>
     concept __pipe_invocable
@@ -1245,6 +1258,7 @@ namespace views::__adaptor
 #endif
     };
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
   // A partial specialization of the above primary template for the case where
   // both adaptor operands have a simple operator().  This in turn lets us
   // implement composition using a single simple operator(), which makes
@@ -1271,6 +1285,7 @@ namespace views::__adaptor
 
       static constexpr bool _S_has_simple_call_op = true;
     };
+#endif // _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
 } // namespace views::__adaptor
 
 #if __cpp_lib_ranges >= 202202L
@@ -1454,7 +1469,9 @@ namespace views::__adaptor
            return owning_view{std::forward<_Range>(__r)};
        }
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_call_op = true;
+#endif
     };
 
     inline constexpr _All all;
@@ -1872,7 +1889,9 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_Filter>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _Filter filter;
@@ -2260,7 +2279,9 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_Transform>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _Transform transform;
@@ -2494,12 +2515,14 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_Take>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       // The count argument of views::take is not always simple -- it can be
       // e.g. a move-only class that's implicitly convertible to the difference
       // type.  But an integer-like count argument is surely simple.
       template<typename _Tp>
        static constexpr bool _S_has_simple_extra_args
          = ranges::__detail::__is_integer_like<_Tp>;
+#endif
     };
 
     inline constexpr _Take take;
@@ -2621,7 +2644,9 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_TakeWhile>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _TakeWhile take_while;
@@ -2777,9 +2802,11 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_Drop>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       template<typename _Tp>
        static constexpr bool _S_has_simple_extra_args
          = _Take::_S_has_simple_extra_args<_Tp>;
+#endif
     };
 
     inline constexpr _Drop drop;
@@ -2866,7 +2893,9 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_DropWhile>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _DropWhile drop_while;
@@ -3273,7 +3302,9 @@ namespace views::__adaptor
          return join_view<all_t<_Range>>{std::forward<_Range>(__r)};
        }
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_call_op = true;
+#endif
     };
 
     inline constexpr _Join join;
@@ -3730,6 +3761,7 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_LazySplit>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       // The pattern argument of views::lazy_split is not always simple -- it 
can be
       // a non-view range, the value category of which affects whether the call
       // is well-formed.  But a scalar or a view pattern argument is surely
@@ -3738,6 +3770,7 @@ namespace views::__adaptor
        static constexpr bool _S_has_simple_extra_args
          = is_scalar_v<_Pattern> || (view<_Pattern>
                                      && copy_constructible<_Pattern>);
+#endif
     };
 
     inline constexpr _LazySplit lazy_split;
@@ -3937,9 +3970,11 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_Split>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       template<typename _Pattern>
        static constexpr bool _S_has_simple_extra_args
          = _LazySplit::_S_has_simple_extra_args<_Pattern>;
+#endif
     };
 
     inline constexpr _Split split;
@@ -4074,7 +4109,9 @@ namespace views::__adaptor
            return common_view{std::forward<_Range>(__r)};
        }
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_call_op = true;
+#endif
     };
 
     inline constexpr _Common common;
@@ -4207,7 +4244,9 @@ namespace views::__adaptor
            return reverse_view{std::forward<_Range>(__r)};
        }
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_call_op = true;
+#endif
     };
 
     inline constexpr _Reverse reverse;
@@ -4598,7 +4637,9 @@ namespace views::__adaptor
            return elements_view<all_t<_Range>, _Nm>{std::forward<_Range>(__r)};
          }
 
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
        static constexpr bool _S_has_simple_call_op = true;
+#endif
       };
 
     template<size_t _Nm>
@@ -6061,7 +6102,9 @@ namespace views::__adaptor
 
        using __adaptor::_RangeAdaptor<_AdjacentTransform>::operator();
        static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
        static constexpr bool _S_has_simple_extra_args = true;
+#endif
       };
 
     template<size_t _Nm>
@@ -6617,7 +6660,9 @@ namespace views::__adaptor
 
       using __adaptor::_RangeAdaptor<_Chunk>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _Chunk chunk;
@@ -6992,7 +7037,9 @@ namespace views::__adaptor
 
       using __adaptor::_RangeAdaptor<_Slide>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _Slide slide;
@@ -7187,7 +7234,9 @@ namespace views::__adaptor
 
       using __adaptor::_RangeAdaptor<_ChunkBy>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _ChunkBy chunk_by;
@@ -7715,9 +7764,11 @@ namespace views::__adaptor
 
       using _RangeAdaptor<_JoinWith>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       template<typename _Pattern>
        static constexpr bool _S_has_simple_extra_args
          = _LazySplit::_S_has_simple_extra_args<_Pattern>;
+#endif
     };
 
     inline constexpr _JoinWith join_with;
@@ -8333,7 +8384,9 @@ namespace views::__adaptor
 
       using __adaptor::_RangeAdaptor<_Stride>::operator();
       static constexpr int _S_arity = 2;
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
       static constexpr bool _S_has_simple_extra_args = true;
+#endif
     };
 
     inline constexpr _Stride stride;
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/100577.cc 
b/libstdc++-v3/testsuite/std/ranges/adaptors/100577.cc
index 53c81be7f02..eaa8454b318 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/100577.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/100577.cc
@@ -31,6 +31,7 @@ namespace views = std::ranges::views;
 void
 test01()
 {
+#ifdef _GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING
   // Verify adaptors are deemed to have simple extra arguments when 
appropriate.
   using views::__adaptor::__adaptor_has_simple_extra_args;
   using std::identity;
@@ -78,6 +79,7 @@ test01()
   static_assert(!__closure_has_simple_call_op<decltype(a12a | a00)>);
   static_assert(!__closure_has_simple_call_op<decltype(a00 | a12a)>);
 #endif
+#endif
 }
 
 void
@@ -135,7 +137,7 @@ test03()
 void
 test04()
 {
-#if __STDC_HOSTED__
+#if defined(_GLIBCXX_RANGES_SIMPLIFY_ADAPTOR_FORWARDING) && __STDC_HOSTED__
   // Non-trivially-copyable extra arguments make a closure not simple.
   using F = std::function<bool(bool)>;
   static_assert(!std::is_trivially_copyable_v<F>);
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc 
b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index dfc91fb5e1f..934d2f65dcf 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -191,8 +191,10 @@ test09()
 #if __cpp_lib_ranges >= 202207L
   // P2494R2 Relaxing range adaptors to allow for move only types
   static_assert( requires { transform(x, move_only{}); } );
+  static_assert( requires { x | transform(move_only{}); } ); // PR 
libstdc++/118413
 #else
   static_assert( ! requires { transform(x, move_only{}); } );
+  static_assert( ! requires { x | transform(move_only{}); } );
 #endif
 }
 
-- 
2.48.1.91.g5f8f7081f7

Reply via email to