public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316
  2020-02-17 22:02 [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Patrick Palka
@ 2020-02-17 22:02 ` Patrick Palka
  2020-02-18 13:52   ` Jonathan Wakely
  2020-02-18 13:50 ` [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Jonathan Wakely
  1 sibling, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-02-17 22:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, jwakely, Patrick Palka

libstdc++-v3/ChangeLog:

	P2106R0
	* include/bits/ranges_algo.h (in_fun_result): New.
	(for_each_result, for_each_n_result): Change into an alias of
	in_fun_result.
	(in_in_result): New.
	(mismatch_result): Change into an alias of in_in_result.
	(copy_if_result): Change into an alias of in_out_result.
	(swap_ranges_result): Change into an alias of in_in_result.
	(unary_transform_result): Change into an alias of in_out_result.
	(in_in_out_result): New.
	(binary_transform_result): Change into an alias of in_in_out_result.
	(replace_copy_result, replace_copy_if_result, remove_copy_if_result,
	remove_copy_result, unique_copy_result, reverse_copy_result,
	rotate_copy_result, partial_sort_copy_result): Change into an alias of
	in_out_result.
	(in_out_out_result): New.
	(partition_copy_result, merge_result): Change into an alias of
	in_out_out_result.
	(set_union_result, set_intersection_result): Change into an alias of
	in_in_out_result.
	(set_difference_result): Change into an alias of in_out_result.
	(set_symmetric_difference): Change into an alias of in_in_out_result.
	(min_max_result): New.
	(minmax_result, minmax_element_result): Change into an alias of
	min_max_result.
	(in_found_result): New.
	(next_permutation_result, prev_permutation_result): Change into an alias
	of in_found_result.
	(__next_permutation_fn::operator(), __prev_permutation_fn::operator()):
	Adjust following changes to next_permutation_result and
	prev_permutation_result.
	* include/bits/ranges_algobase.h (in_out_result): New.
	(copy_result, move_result, move_backward_result, copy_backward_result,
	copy_n_result): Change into an alias of in_out_result.
	* include/bits/ranges_uninitialized.h (uninitialized_copy_result,
	uninitialized_copy_n_result, uninitialized_move_result,
	uninitialized_move_n_result): Likewise.
	* testsuite/25_algorithms/next_permutation/constrained.cc: Adjust uses of
	structured bindings.
	* testsuite/25_algorithms/prev_permutation/constrained.cc: Likewise.
---
 libstdc++-v3/include/bits/ranges_algo.h       | 137 +++++++++++-------
 libstdc++-v3/include/bits/ranges_algobase.h   |  19 ++-
 .../include/bits/ranges_uninitialized.h       |   8 +-
 .../next_permutation/constrained.cc           |   4 +-
 .../prev_permutation/constrained.cc           |   4 +-
 5 files changed, 108 insertions(+), 64 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index c50b369c6c0..31b1bf0d448 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -152,7 +152,7 @@ namespace ranges
   inline constexpr __none_of_fn none_of{};
 
   template<typename _Iter, typename _Fp>
-    struct for_each_result
+    struct in_fun_result
     {
       [[no_unique_address]] _Iter in;
       [[no_unique_address]] _Fp fun;
@@ -160,15 +160,20 @@ namespace ranges
       template<typename _Iter2, typename _F2p>
 	requires convertible_to<const _Iter&, _Iter2>
 	  && convertible_to<const _Fp&, _F2p>
-	operator for_each_result<_Iter2, _F2p>() const &
+	constexpr
+	operator in_fun_result<_Iter2, _F2p>() const &
 	{ return {in, fun}; }
 
       template<typename _Iter2, typename _F2p>
 	requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p>
-	operator for_each_result<_Iter2, _F2p>() &&
+	constexpr
+	operator in_fun_result<_Iter2, _F2p>() &&
 	{ return {std::move(in), std::move(fun)}; }
     };
 
+  template<typename _Iter, typename _Fp>
+    using for_each_result = in_fun_result<_Iter, _Fp>;
+
   struct __for_each_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -196,7 +201,7 @@ namespace ranges
   inline constexpr __for_each_fn for_each{};
 
   template<typename _Iter, typename _Fp>
-    using for_each_n_result = for_each_result<_Iter, _Fp>;
+    using for_each_n_result = in_fun_result<_Iter, _Fp>;
 
   struct __for_each_n_fn
   {
@@ -416,7 +421,7 @@ namespace ranges
   inline constexpr __count_if_fn count_if{};
 
   template<typename _Iter1, typename _Iter2>
-    struct mismatch_result
+    struct in_in_result
     {
       [[no_unique_address]] _Iter1 in1;
       [[no_unique_address]] _Iter2 in2;
@@ -424,16 +429,21 @@ namespace ranges
       template<typename _IIter1, typename _IIter2>
 	requires convertible_to<const _Iter1&, _IIter1>
 	  && convertible_to<const _Iter2&, _IIter2>
-	operator mismatch_result<_IIter1, _IIter2>() const &
+	constexpr
+	operator in_in_result<_IIter1, _IIter2>() const &
 	{ return {in1, in2}; }
 
       template<typename _IIter1, typename _IIter2>
 	requires convertible_to<_Iter1, _IIter1>
 	  && convertible_to<_Iter2, _IIter2>
-	operator mismatch_result<_IIter1, _IIter2>() &&
+	constexpr
+	operator in_in_result<_IIter1, _IIter2>() &&
 	{ return {std::move(in1), std::move(in2)}; }
     };
 
+  template<typename _Iter1, typename _Iter2>
+    using mismatch_result = in_in_result<_Iter1, _Iter2>;
+
   struct __mismatch_fn
   {
     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
@@ -830,7 +840,7 @@ namespace ranges
   inline constexpr __is_permutation_fn is_permutation{};
 
   template<typename _Iter, typename _Out>
-    using copy_if_result = copy_result<_Iter, _Out>;
+    using copy_if_result = in_out_result<_Iter, _Out>;
 
   struct __copy_if_fn
   {
@@ -869,7 +879,7 @@ namespace ranges
   inline constexpr __copy_if_fn copy_if{};
 
   template<typename _Iter1, typename _Iter2>
-    using swap_ranges_result = mismatch_result<_Iter1, _Iter2>;
+    using swap_ranges_result = in_in_result<_Iter1, _Iter2>;
 
   struct __swap_ranges_fn
   {
@@ -900,10 +910,10 @@ namespace ranges
   inline constexpr __swap_ranges_fn swap_ranges{};
 
   template<typename _Iter, typename _Out>
-    using unary_transform_result = copy_result<_Iter, _Out>;
+    using unary_transform_result = in_out_result<_Iter, _Out>;
 
   template<typename _Iter1, typename _Iter2, typename _Out>
-    struct binary_transform_result
+    struct in_in_out_result
     {
       [[no_unique_address]] _Iter1 in1;
       [[no_unique_address]] _Iter2 in2;
@@ -913,17 +923,22 @@ namespace ranges
 	requires convertible_to<const _Iter1&, _IIter1>
 	  && convertible_to<const _Iter2&, _IIter2>
 	  && convertible_to<const _Out&, _OOut>
-	operator binary_transform_result<_IIter1, _IIter2, _OOut>() const &
+	constexpr
+	operator in_in_out_result<_IIter1, _IIter2, _OOut>() const &
 	{ return {in1, in2, out}; }
 
       template<typename _IIter1, typename _IIter2, typename _OOut>
 	requires convertible_to<_Iter1, _IIter1>
 	  && convertible_to<_Iter2, _IIter2>
 	  && convertible_to<_Out, _OOut>
-	operator binary_transform_result<_IIter1, _IIter2, _OOut>() &&
+	constexpr
+	operator in_in_out_result<_IIter1, _IIter2, _OOut>() &&
 	{ return {std::move(in1), std::move(in2), std::move(out)}; }
     };
 
+  template<typename _Iter1, typename _Iter2, typename _Out>
+    using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>;
+
   struct __transform_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -1065,7 +1080,7 @@ namespace ranges
   inline constexpr __replace_if_fn replace_if{};
 
   template<typename _Iter, typename _Out>
-    using replace_copy_result = copy_result<_Iter, _Out>;
+    using replace_copy_result = in_out_result<_Iter, _Out>;
 
   struct __replace_copy_fn
   {
@@ -1108,7 +1123,7 @@ namespace ranges
   inline constexpr __replace_copy_fn replace_copy{};
 
   template<typename _Iter, typename _Out>
-    using replace_copy_if_result = copy_result<_Iter, _Out>;
+    using replace_copy_if_result = in_out_result<_Iter, _Out>;
 
   struct __replace_copy_if_fn
   {
@@ -1261,7 +1276,7 @@ namespace ranges
   inline constexpr __remove_fn remove{};
 
   template<typename _Iter, typename _Out>
-    using remove_copy_if_result = copy_result<_Iter, _Out>;
+    using remove_copy_if_result = in_out_result<_Iter, _Out>;
 
   struct __remove_copy_if_fn
   {
@@ -1300,7 +1315,7 @@ namespace ranges
   inline constexpr __remove_copy_if_fn remove_copy_if{};
 
   template<typename _Iter, typename _Out>
-    using remove_copy_result = copy_result<_Iter, _Out>;
+    using remove_copy_result = in_out_result<_Iter, _Out>;
 
   struct __remove_copy_fn
   {
@@ -1379,7 +1394,7 @@ namespace ranges
   inline constexpr __unique_fn unique{};
 
   template<typename _Iter, typename _Out>
-    using unique_copy_result = copy_result<_Iter, _Out>;
+    using unique_copy_result = in_out_result<_Iter, _Out>;
 
   struct __unique_copy_fn
   {
@@ -1514,7 +1529,7 @@ namespace ranges
   inline constexpr __reverse_fn reverse{};
 
   template<typename _Iter, typename _Out>
-    using reverse_copy_result = copy_result<_Iter, _Out>;
+    using reverse_copy_result = in_out_result<_Iter, _Out>;
 
   struct __reverse_copy_fn
   {
@@ -1695,7 +1710,7 @@ namespace ranges
   inline constexpr __rotate_fn rotate{};
 
   template<typename _Iter, typename _Out>
-    using rotate_copy_result = copy_result<_Iter, _Out>;
+    using rotate_copy_result = in_out_result<_Iter, _Out>;
 
   struct __rotate_copy_fn
   {
@@ -2093,7 +2108,7 @@ namespace ranges
   inline constexpr __partial_sort_fn partial_sort{};
 
   template<typename _Iter, typename _Out>
-    using partial_sort_copy_result = copy_result<_Iter, _Out>;
+    using partial_sort_copy_result = in_out_result<_Iter, _Out>;
 
   struct __partial_sort_copy_fn
   {
@@ -2580,28 +2595,33 @@ namespace ranges
 
   inline constexpr __stable_partition_fn stable_partition{};
 
-  template<typename _Iter, typename _Out1, typename _O2>
-    struct partition_copy_result
+  template<typename _Iter, typename _Out1, typename _Out2>
+    struct in_out_out_result
     {
       [[no_unique_address]] _Iter  in;
       [[no_unique_address]] _Out1 out1;
-      [[no_unique_address]] _O2 out2;
+      [[no_unique_address]] _Out2 out2;
 
       template<typename _IIter, typename _OOut1, typename _OOut2>
 	requires convertible_to<const _Iter&, _IIter>
 	  && convertible_to<const _Out1&, _OOut1>
-	  && convertible_to<const _O2&, _OOut2>
-	operator partition_copy_result<_IIter, _OOut1, _OOut2>() const &
+	  && convertible_to<const _Out2&, _OOut2>
+	constexpr
+	operator in_out_out_result<_IIter, _OOut1, _OOut2>() const &
 	{ return {in, out1, out2}; }
 
       template<typename _IIter, typename _OOut1, typename _OOut2>
 	requires convertible_to<_Iter, _IIter>
 	  && convertible_to<_Out1, _OOut1>
-	  && convertible_to<_O2, _OOut2>
-	operator partition_copy_result<_IIter, _OOut1, _OOut2>() &&
+	  && convertible_to<_Out2, _OOut2>
+	constexpr
+	operator in_out_out_result<_IIter, _OOut1, _OOut2>() &&
 	{ return {std::move(in), std::move(out1), std::move(out2)}; }
     };
 
+  template<typename _Iter, typename _Out1, typename _Out2>
+    using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>;
+
   struct __partition_copy_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -2692,7 +2712,7 @@ namespace ranges
   inline constexpr __partition_point_fn partition_point{};
 
   template<typename _Iter1, typename _Iter2, typename _Out>
-    using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>;
+    using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>;
 
   struct __merge_fn
   {
@@ -2834,7 +2854,7 @@ namespace ranges
   inline constexpr __includes_fn includes{};
 
   template<typename _Iter1, typename _Iter2, typename _Out>
-    using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>;
+    using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>;
 
   struct __set_union_fn
   {
@@ -2902,8 +2922,7 @@ namespace ranges
   inline constexpr __set_union_fn set_union{};
 
   template<typename _Iter1, typename _Iter2, typename _Out>
-    using set_intersection_result
-      = binary_transform_result<_Iter1, _Iter2, _Out>;
+    using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>;
 
   struct __set_intersection_fn
   {
@@ -2961,7 +2980,7 @@ namespace ranges
   inline constexpr __set_intersection_fn set_intersection{};
 
   template<typename _Iter, typename _Out>
-    using set_difference_result = copy_result<_Iter, _Out>;
+    using set_difference_result = in_out_result<_Iter, _Out>;
 
   struct __set_difference_fn
   {
@@ -3019,7 +3038,7 @@ namespace ranges
 
   template<typename _Iter1, typename _Iter2, typename _Out>
     using set_symmetric_difference_result
-      = binary_transform_result<_Iter1, _Iter2, _Out>;
+      = in_in_out_result<_Iter1, _Iter2, _Out>;
 
   struct __set_symmetric_difference_fn
   {
@@ -3218,22 +3237,27 @@ namespace ranges
   inline constexpr __clamp_fn clamp{};
 
   template<typename _Tp>
-    struct minmax_result
+    struct min_max_result
     {
       [[no_unique_address]] _Tp min;
       [[no_unique_address]] _Tp max;
 
       template<typename _Tp2>
 	requires convertible_to<const _Tp&, _Tp2>
-	operator minmax_result<_Tp2>() const &
+	constexpr
+	operator min_max_result<_Tp2>() const &
 	{ return {min, max}; }
 
       template<typename _Tp2>
 	requires convertible_to<_Tp, _Tp2>
-	operator minmax_result<_Tp2>() &&
+	constexpr
+	operator min_max_result<_Tp2>() &&
 	{ return {std::move(min), std::move(max)}; }
     };
 
+  template<typename _Tp>
+    using minmax_result = min_max_result<_Tp>;
+
   struct __minmax_fn
   {
     template<typename _Tp, typename _Proj = identity,
@@ -3367,7 +3391,7 @@ namespace ranges
   inline constexpr __max_element_fn max_element{};
 
   template<typename _Iter>
-    using minmax_element_result = minmax_result<_Iter>;
+    using minmax_element_result = min_max_result<_Iter>;
 
   struct __minmax_element_fn
   {
@@ -3516,12 +3540,27 @@ namespace ranges
   inline constexpr __lexicographical_compare_fn lexicographical_compare;
 
   template<typename _Iter>
-    struct next_permutation_result
+    struct in_found_result
     {
+      [[no_unique_address]] _Iter in;
       bool found;
-      _Iter in;
+
+      template<typename _Iter2>
+	requires convertible_to<const _Iter&, _Iter2>
+	constexpr
+	operator in_found_result<_Iter2>() const &
+	{ return {in, found}; }
+
+      template<typename _Iter2>
+	requires convertible_to<_Iter, _Iter2>
+	constexpr
+	operator in_found_result<_Iter2>() &&
+	{ return {std::move(in), found}; }
     };
 
+  template<typename _Iter>
+    using next_permutation_result = in_found_result<_Iter>;
+
   struct __next_permutation_fn
   {
     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -3532,12 +3571,12 @@ namespace ranges
 		 _Comp __comp = {}, _Proj __proj = {}) const
       {
 	if (__first == __last)
-	  return {false, std::move(__first)};
+	  return {std::move(__first), false};
 
 	auto __i = __first;
 	++__i;
 	if (__i == __last)
-	  return {false, std::move(__i)};
+	  return {std::move(__i), false};
 
 	auto __lasti = ranges::next(__first, __last);
 	__i = __lasti;
@@ -3558,12 +3597,12 @@ namespace ranges
 		  ;
 		ranges::iter_swap(__i, __j);
 		ranges::reverse(__ii, __last);
-		return {true, std::move(__lasti)};
+		return {std::move(__lasti), true};
 	      }
 	    if (__i == __first)
 	      {
 		ranges::reverse(__first, __last);
-		return {false, std::move(__lasti)};
+		return {std::move(__lasti), false};
 	      }
 	  }
       }
@@ -3582,7 +3621,7 @@ namespace ranges
   inline constexpr __next_permutation_fn next_permutation{};
 
   template<typename _Iter>
-    using prev_permutation_result = next_permutation_result<_Iter>;
+    using prev_permutation_result = in_found_result<_Iter>;
 
   struct __prev_permutation_fn
   {
@@ -3594,12 +3633,12 @@ namespace ranges
 		 _Comp __comp = {}, _Proj __proj = {}) const
       {
 	if (__first == __last)
-	  return {false, std::move(__first)};
+	  return {std::move(__first), false};
 
 	auto __i = __first;
 	++__i;
 	if (__i == __last)
-	  return {false, std::move(__i)};
+	  return {std::move(__i), false};
 
 	auto __lasti = ranges::next(__first, __last);
 	__i = __lasti;
@@ -3620,12 +3659,12 @@ namespace ranges
 		  ;
 		ranges::iter_swap(__i, __j);
 		ranges::reverse(__ii, __last);
-		return {true, std::move(__lasti)};
+		return {std::move(__lasti), true};
 	      }
 	    if (__i == __first)
 	      {
 		ranges::reverse(__first, __last);
-		return {false, std::move(__lasti)};
+		return {std::move(__lasti), false};
 	      }
 	  }
       }
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index eedd29f570a..7424766f053 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -157,7 +157,7 @@ namespace ranges
   inline constexpr __equal_fn equal{};
 
   template<typename _Iter, typename _Out>
-    struct copy_result
+    struct in_out_result
     {
       [[no_unique_address]] _Iter in;
       [[no_unique_address]] _Out out;
@@ -165,24 +165,29 @@ namespace ranges
       template<typename _Iter2, typename _Out2>
 	requires convertible_to<const _Iter&, _Iter2>
 	  && convertible_to<const _Out&, _Out2>
-	operator copy_result<_Iter2, _Out2>() const &
+	constexpr
+	operator in_out_result<_Iter2, _Out2>() const &
 	{ return {in, out}; }
 
       template<typename _Iter2, typename _Out2>
 	requires convertible_to<_Iter, _Iter2>
 	  && convertible_to<_Out, _Out2>
-	operator copy_result<_Iter2, _Out2>() &&
+	constexpr
+	operator in_out_result<_Iter2, _Out2>() &&
 	{ return {std::move(in), std::move(out)}; }
     };
 
   template<typename _Iter, typename _Out>
-    using move_result = copy_result<_Iter, _Out>;
+    using copy_result = in_out_result<_Iter, _Out>;
+
+  template<typename _Iter, typename _Out>
+    using move_result = in_out_result<_Iter, _Out>;
 
   template<typename _Iter1, typename _Iter2>
-    using move_backward_result = copy_result<_Iter1, _Iter2>;
+    using move_backward_result = in_out_result<_Iter1, _Iter2>;
 
   template<typename _Iter1, typename _Iter2>
-    using copy_backward_result = copy_result<_Iter1, _Iter2>;
+    using copy_backward_result = in_out_result<_Iter1, _Iter2>;
 
   template<bool _IsMove,
 	   bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
@@ -483,7 +488,7 @@ namespace ranges
   inline constexpr __move_backward_fn move_backward{};
 
   template<typename _Iter, typename _Out>
-    using copy_n_result = copy_result<_Iter, _Out>;
+    using copy_n_result = in_out_result<_Iter, _Out>;
 
   struct __copy_n_fn
   {
diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h
index bbf683de066..881bf39d5f8 100644
--- a/libstdc++-v3/include/bits/ranges_uninitialized.h
+++ b/libstdc++-v3/include/bits/ranges_uninitialized.h
@@ -253,7 +253,7 @@ namespace ranges
     uninitialized_value_construct_n;
 
   template<typename _Iter, typename _Out>
-    using uninitialized_copy_result = copy_result<_Iter, _Out>;
+    using uninitialized_copy_result = in_out_result<_Iter, _Out>;
 
   struct __uninitialized_copy_fn
   {
@@ -302,7 +302,7 @@ namespace ranges
   inline constexpr __uninitialized_copy_fn uninitialized_copy{};
 
   template<typename _Iter, typename _Out>
-    using uninitialized_copy_n_result = uninitialized_copy_result<_Iter, _Out>;
+    using uninitialized_copy_n_result = in_out_result<_Iter, _Out>;
 
   struct __uninitialized_copy_n_fn
   {
@@ -337,7 +337,7 @@ namespace ranges
   inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{};
 
   template<typename _Iter, typename _Out>
-    using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>;
+    using uninitialized_move_result = in_out_result<_Iter, _Out>;
 
   struct __uninitialized_move_fn
   {
@@ -389,7 +389,7 @@ namespace ranges
   inline constexpr __uninitialized_move_fn uninitialized_move{};
 
   template<typename _Iter, typename _Out>
-    using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>;
+    using uninitialized_move_n_result = in_out_result<_Iter, _Out>;
 
   struct __uninitialized_move_n_fn
   {
diff --git a/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc
index e69b551a56b..b397a4e8ed7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc
@@ -41,7 +41,7 @@ test01()
       for (int j = 0; ; j++)
 	{
 	  auto found1 = std::next_permutation(cx.begin(), cx.end());
-	  auto [found2,last] = ranges::next_permutation(cy.begin(), cy.end());
+	  auto [last,found2] = ranges::next_permutation(cy.begin(), cy.end());
 	  VERIFY( found1 == found2 );
 	  VERIFY( ranges::equal(cx, cy) );
 	  if (!found2)
@@ -55,7 +55,7 @@ test02()
 {
   int x[] = {5, 4, 3, 2, 1};
   test_range<int, bidirectional_iterator_wrapper> rx(x);
-  auto [found,last] = ranges::next_permutation(rx, ranges::greater{});
+  auto [last,found] = ranges::next_permutation(rx, ranges::greater{});
   VERIFY( found && last == rx.end() );
   VERIFY( last == rx.end() );
   VERIFY( ranges::equal(rx, (int[]){5,4,3,1,2}) );
diff --git a/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc
index 25bbad9be0c..22f1329b4c7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc
@@ -41,7 +41,7 @@ test01()
       for (int j = 0; ; j++)
 	{
 	  auto found1 = std::prev_permutation(cx.begin(), cx.end());
-	  auto [found2,last] = ranges::prev_permutation(cy.begin(), cy.end());
+	  auto [last,found2] = ranges::prev_permutation(cy.begin(), cy.end());
 	  VERIFY( found1 == found2 );
 	  VERIFY( ranges::equal(cx, cy) );
 	  if (!found2)
@@ -55,7 +55,7 @@ test02()
 {
   int x[] = {1, 2, 3, 4, 5};
   test_range<int, bidirectional_iterator_wrapper> rx(x);
-  auto [found,last] = ranges::prev_permutation(rx, ranges::greater{});
+  auto [last,found] = ranges::prev_permutation(rx, ranges::greater{});
   VERIFY( found && last == rx.end() );
   VERIFY( last == rx.end() );
   VERIFY( ranges::equal(rx, (int[]){1,2,3,5,4}) );
-- 
2.25.1.291.ge68e29171c

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms
@ 2020-02-17 22:02 Patrick Palka
  2020-02-17 22:02 ` [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316 Patrick Palka
  2020-02-18 13:50 ` [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Jonathan Wakely
  0 siblings, 2 replies; 4+ messages in thread
From: Patrick Palka @ 2020-02-17 22:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, jwakely, Patrick Palka

This adds rangified overloads for for_each_n, sample and clamp as per P1243R4.

libstdc++-v3/ChangeLog:

	P1243R4
	* include/bits/ranges_algo.h (for_each_n_result, __for_each_n_fn,
	for_each_n, __sample_fn, sample, __clamp_fn, clamp): New.
	* testsuite/25_algorithms/clamp/constrained.cc: New test.
	* testsuite/25_algorithms/for_each/constrained.cc: Augment test.
	* testsuite/25_algorithms/sample/constrained.cc: New test.
---
 libstdc++-v3/include/bits/ranges_algo.h       | 115 ++++++++++++++++++
 .../25_algorithms/clamp/constrained.cc        |  58 +++++++++
 .../25_algorithms/for_each/constrained.cc     |  44 +++++++
 .../25_algorithms/sample/constrained.cc       |  68 +++++++++++
 4 files changed, 285 insertions(+)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index 83f295722e9..c50b369c6c0 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -195,6 +195,39 @@ namespace ranges
 
   inline constexpr __for_each_fn for_each{};
 
+  template<typename _Iter, typename _Fp>
+    using for_each_n_result = for_each_result<_Iter, _Fp>;
+
+  struct __for_each_n_fn
+  {
+    template<input_iterator _Iter, typename _Proj = identity,
+	     indirectly_unary_invocable<projected<_Iter, _Proj>> _Fun>
+      constexpr for_each_n_result<_Iter, _Fun>
+      operator()(_Iter __first, iter_difference_t<_Iter> __n,
+		 _Fun __f, _Proj __proj = {}) const
+      {
+	if constexpr (random_access_iterator<_Iter>)
+	  {
+	    if (__n <= 0)
+	      return {std::move(__first), std::move(__f)};
+	    auto __last = __first + __n;
+	    return ranges::for_each(std::move(__first), std::move(__last),
+				    std::move(__f), std::move(__proj));
+	  }
+	else
+	  {
+	    while (__n-- > 0)
+	      {
+		std::__invoke(__f, std::__invoke(__proj, *__first));
+		++__first;
+	      }
+	    return {std::move(__first), std::move(__f)};
+	  }
+      }
+  };
+
+  inline constexpr __for_each_n_fn for_each_n{};
+
   struct __find_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
@@ -1694,6 +1727,64 @@ namespace ranges
 
   inline constexpr __rotate_copy_fn rotate_copy{};
 
+  struct __sample_fn
+  {
+    template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+	     weakly_incrementable _Out, typename _Gen>
+      requires (forward_iterator<_Iter> || random_access_iterator<_Out>)
+	&& indirectly_copyable<_Iter, _Out>
+	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
+      _Out
+      operator()(_Iter __first, _Sent __last, _Out __out,
+		 iter_difference_t<_Iter> __n, _Gen&& __g) const
+      {
+	if constexpr (forward_iterator<_Iter>)
+	  {
+	    // FIXME: Forwarding to std::sample here requires computing __lasti
+	    // which may take linear time.
+	    auto __lasti = ranges::next(__first, __last);
+	    return std::sample(std::move(__first), std::move(__lasti),
+			       std::move(__out), __n, std::forward<_Gen>(__g));
+	  }
+	else
+	  {
+	    using __distrib_type
+	      = uniform_int_distribution<iter_difference_t<_Iter>>;
+	    using __param_type = typename __distrib_type::param_type;
+	    __distrib_type __d{};
+	    iter_difference_t<_Iter> __sample_sz = 0;
+	    while (__first != __last && __sample_sz != __n)
+	      {
+		__out[__sample_sz++] = *__first;
+		++__first;
+	      }
+	    for (auto __pop_sz = __sample_sz; __first != __last;
+		++__first, (void) ++__pop_sz)
+	      {
+		const auto __k = __d(__g, __param_type{0, __pop_sz});
+		if (__k < __n)
+		  __out[__k] = *__first;
+	      }
+	    return __out + __sample_sz;
+	  }
+      }
+
+    template<input_range _Range, weakly_incrementable _Out, typename _Gen>
+      requires (forward_range<_Range> || random_access_iterator<_Out>)
+	&& indirectly_copyable<iterator_t<_Range>, _Out>
+	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
+      _Out
+      operator()(_Range&& __r, _Out __out,
+		 range_difference_t<_Range> __n, _Gen&& __g) const
+      {
+	return (*this)(ranges::begin(__r), ranges::end(__r),
+		       std::move(__out), __n,
+		       std::forward<_Gen>(__g));
+      }
+  };
+
+  inline constexpr __sample_fn sample{};
+
 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
   struct __shuffle_fn
   {
@@ -3102,6 +3193,30 @@ namespace ranges
 
   inline constexpr __max_fn max{};
 
+  struct __clamp_fn
+  {
+    template<typename _Tp, typename _Proj = identity,
+	     indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp
+	       = ranges::less>
+      constexpr const _Tp&
+      operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi,
+		 _Comp __comp = {}, _Proj __proj = {}) const
+      {
+	__glibcxx_assert(!(std::__invoke(__comp,
+					 std::__invoke(__proj, __hi),
+					 std::__invoke(__proj, __lo))));
+	auto&& __proj_val = std::__invoke(__proj, __val);
+	if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo)))
+	  return __lo;
+	else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val))
+	  return __hi;
+	else
+	  return __val;
+      }
+  };
+
+  inline constexpr __clamp_fn clamp{};
+
   template<typename _Tp>
     struct minmax_result
     {
diff --git a/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc
new file mode 100644
index 00000000000..1964bb60354
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/clamp/constrained.cc
@@ -0,0 +1,58 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+  int i, j;
+};
+
+void
+test01()
+{
+  VERIFY( ranges::clamp(1, 2, 4) == 2 );
+  VERIFY( ranges::clamp(3, 2, 4) == 3 );
+  VERIFY( ranges::clamp(5, 2, 4) == 4 );
+
+  VERIFY( ranges::clamp(1, 4, 2, ranges::greater{}) == 2 );
+  VERIFY( ranges::clamp(3, 4, 2, ranges::greater{}) == 3 );
+  VERIFY( ranges::clamp(5, 4, 2, ranges::greater{}) == 4 );
+
+  VERIFY( ranges::clamp(1, 2, 4, ranges::greater{}, std::negate<>{}) == 2 );
+  VERIFY( ranges::clamp(3, 2, 4, ranges::greater{}, std::negate<>{}) == 3 );
+  VERIFY( ranges::clamp(5, 2, 4, ranges::greater{}, std::negate<>{}) == 4 );
+
+  static_assert(ranges::clamp(X{1,2}, X{1,3}, X{1,4}, {}, &X::i).j == 2);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc
index 142ad2e57da..31ca0a7046a 100644
--- a/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc
@@ -26,6 +26,7 @@ using __gnu_test::test_container;
 using __gnu_test::test_range;
 using __gnu_test::input_iterator_wrapper;
 using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
 
 namespace ranges = std::ranges;
 
@@ -75,9 +76,52 @@ test02()
   static_assert(f() == 6);
 }
 
+template<template<typename> typename wrapper>
+void
+test03()
+{
+  int x[] = {1,2,3,4,5};
+  test_range<int, wrapper> rx(x);
+  int s = 0;
+  auto func = [&s](int i){ s += i; };
+  auto [i,f] = ranges::for_each_n(rx.begin(), 3, func);
+  VERIFY( i.ptr = x+3 );
+  VERIFY( s == 1+2+3 );
+  f(1);
+  VERIFY( s == 1+2+3+1 );
+
+  s = 0;
+  rx.bounds.first = x;
+  auto [j,g] = ranges::for_each_n(rx.begin(), -1, func);
+  VERIFY( j.ptr == x );
+  VERIFY( s == 0 );
+  g(1);
+  VERIFY( s == 1 );
+
+  s = 0;
+  rx.bounds.first = x;
+  auto [k,h] = ranges::for_each_n(rx.begin(), 5, func, std::negate<>{});
+  VERIFY( k.ptr == x+5 );
+  VERIFY( s == -(1+2+3+4+5) );
+  h(-6);
+  VERIFY( s == -(1+2+3+4+5+6) );
+}
+
+constexpr bool
+test04()
+{
+  int x[] = {1,2,3,4,5};
+  int p = 1;
+  ranges::for_each_n(x+1, 4, [&p](int i){ p*=i; }, [](int i){ return i+1; });
+  return p == 3*4*5*6;
+}
+
 int
 main()
 {
   test01();
   test02();
+  test03<input_iterator_wrapper>();
+  test03<random_access_iterator_wrapper>();
+  static_assert(test04());
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc
new file mode 100644
index 00000000000..7ed57e8aefc
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/sample/constrained.cc
@@ -0,0 +1,68 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+std::mt19937 rng;
+
+template<template<typename> typename in_wrapper,
+	 template<typename> typename out_wrapper>
+void
+test01()
+{
+  const int x[] = {1,2,3,4,5,6,7,8,9,10};
+  test_range<const int, in_wrapper> rx(x);
+  int y[10];
+  test_range<int, out_wrapper> ry(y);
+  auto out = ranges::sample(rx.begin(), rx.end(), ry.begin(), 20, rng);
+  VERIFY( out.ptr == y+10 );
+  VERIFY( ranges::equal(x, y) );
+
+  for (int i = 0; i < 100; i++)
+    {
+      int z[5] = {0};
+      test_range<int, out_wrapper> rz(z);
+      rx.bounds.first = x;
+      auto out = ranges::sample(rx, rz.begin(), 5, rng);
+      VERIFY( out.ptr == z+5 );
+      ranges::sort(z);
+      VERIFY( ranges::adjacent_find(z) == out.ptr );
+      VERIFY( ranges::includes(x, z) );
+    }
+}
+
+int
+main()
+{
+  test01<forward_iterator_wrapper, output_iterator_wrapper>();
+  test01<input_iterator_wrapper, random_access_iterator_wrapper>();
+}
-- 
2.25.1.291.ge68e29171c

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms
  2020-02-17 22:02 [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Patrick Palka
  2020-02-17 22:02 ` [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316 Patrick Palka
@ 2020-02-18 13:50 ` Jonathan Wakely
  1 sibling, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2020-02-18 13:50 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On 17/02/20 17:00 -0500, Patrick Palka wrote:
>This adds rangified overloads for for_each_n, sample and clamp as per P1243R4.
>
>libstdc++-v3/ChangeLog:
>
>	P1243R4
>	* include/bits/ranges_algo.h (for_each_n_result, __for_each_n_fn,
>	for_each_n, __sample_fn, sample, __clamp_fn, clamp): New.
>	* testsuite/25_algorithms/clamp/constrained.cc: New test.
>	* testsuite/25_algorithms/for_each/constrained.cc: Augment test.
>	* testsuite/25_algorithms/sample/constrained.cc: New test.

OK, thanks.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316
  2020-02-17 22:02 ` [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316 Patrick Palka
@ 2020-02-18 13:52   ` Jonathan Wakely
  0 siblings, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2020-02-18 13:52 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On 17/02/20 17:00 -0500, Patrick Palka wrote:
>libstdc++-v3/ChangeLog:
>
>	P2106R0
>	* include/bits/ranges_algo.h (in_fun_result): New.
>	(for_each_result, for_each_n_result): Change into an alias of
>	in_fun_result.
>	(in_in_result): New.
>	(mismatch_result): Change into an alias of in_in_result.
>	(copy_if_result): Change into an alias of in_out_result.
>	(swap_ranges_result): Change into an alias of in_in_result.
>	(unary_transform_result): Change into an alias of in_out_result.
>	(in_in_out_result): New.
>	(binary_transform_result): Change into an alias of in_in_out_result.
>	(replace_copy_result, replace_copy_if_result, remove_copy_if_result,
>	remove_copy_result, unique_copy_result, reverse_copy_result,
>	rotate_copy_result, partial_sort_copy_result): Change into an alias of
>	in_out_result.
>	(in_out_out_result): New.
>	(partition_copy_result, merge_result): Change into an alias of
>	in_out_out_result.
>	(set_union_result, set_intersection_result): Change into an alias of
>	in_in_out_result.
>	(set_difference_result): Change into an alias of in_out_result.
>	(set_symmetric_difference): Change into an alias of in_in_out_result.
>	(min_max_result): New.
>	(minmax_result, minmax_element_result): Change into an alias of
>	min_max_result.
>	(in_found_result): New.
>	(next_permutation_result, prev_permutation_result): Change into an alias
>	of in_found_result.
>	(__next_permutation_fn::operator(), __prev_permutation_fn::operator()):
>	Adjust following changes to next_permutation_result and
>	prev_permutation_result.
>	* include/bits/ranges_algobase.h (in_out_result): New.
>	(copy_result, move_result, move_backward_result, copy_backward_result,
>	copy_n_result): Change into an alias of in_out_result.
>	* include/bits/ranges_uninitialized.h (uninitialized_copy_result,
>	uninitialized_copy_n_result, uninitialized_move_result,
>	uninitialized_move_n_result): Likewise.
>	* testsuite/25_algorithms/next_permutation/constrained.cc: Adjust uses of
>	structured bindings.
>	* testsuite/25_algorithms/prev_permutation/constrained.cc: Likewise.

OK, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-02-18 13:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-17 22:02 [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Patrick Palka
2020-02-17 22:02 ` [PATCH 2/2] libstdc++: P2106R0 Alternative wording for GB315 and GB316 Patrick Palka
2020-02-18 13:52   ` Jonathan Wakely
2020-02-18 13:50 ` [PATCH 1/2] libstdc++: P1243R4 Rangify new algorithms Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).