[gcc r16-9408] libstdc++: Implement LWG 4074 changes to join_with_view's constraints

Patrick Palka via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <20260726140529.90F394BA5434__39149.9589941063$1785074738$gmane$org@sourceware.org>
https://gcc.gnu.org/g:67669313cebbb618d5a9046baaeb69ca885183f2

commit r16-9408-g67669313cebbb618d5a9046baaeb69ca885183f2
Author: Patrick Palka <[email protected]>
Date:   Sat Jul 25 16:12:16 2026 -0400

    libstdc++: Implement LWG 4074 changes to join_with_view's constraints
    
    libstdc++-v3/ChangeLog:
    
            * include/std/ranges (__detail::__compatible_joinable_ranges):
            Remove.
            (__detail::__concat_reference_t): Move definition up.
            (__detail::__concat_value_t): Likewise.
            (__detail::__concat_rvalue_reference_t): Likewise.
            (__detail::__concat_indirectly_readable_impl): Likewise.
            (__detail::__concat_indirectly_readable): Likewise.
            (__detail::__concatable): Likewise.
            (join_with_view): Use __concatable instead of
            __compatible_joinable_ranges in constraints as per LWG 4074.
            (join_with_view::begin): Add __concatable constraint as per
            LWG 4074.
            (join_with_view::end): Likewise.
            (join_with_view::_Iterator): Adjust out-of-line declaration.
            (join_with_view::_Sentinel): Likewise.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    (cherry picked from commit 368574dc98d3ad15fd099080965826e2afda963c)

Diff:
---
 libstdc++-v3/include/std/ranges | 88 ++++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 46 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 686ed93a916d..92a2ae6db0f7 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -7347,22 +7347,51 @@ namespace views::__adaptor
 #ifdef __cpp_lib_ranges_join_with // C++ >= 23
   namespace __detail
   {
-    template<typename _Range, typename _Pattern>
-      concept __compatible_joinable_ranges
-	= common_with<range_value_t<_Range>, range_value_t<_Pattern>>
-	  && common_reference_with<range_reference_t<_Range>,
-				   range_reference_t<_Pattern>>
-	  && common_reference_with<range_rvalue_reference_t<_Range>,
-				   range_rvalue_reference_t<_Pattern>>;
-
     template<typename _Range>
       concept __bidirectional_common = bidirectional_range<_Range> && common_range<_Range>;
+
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // 4074. compatible-joinable-ranges is underconstrained
+    template<typename... _Rs>
+      using __concat_reference_t = common_reference_t<range_reference_t<_Rs>...>;
+
+    template<typename... _Rs>
+      using __concat_value_t = common_type_t<range_value_t<_Rs>...>;
+
+    template<typename... _Rs>
+      using __concat_rvalue_reference_t
+	= common_reference_t<range_rvalue_reference_t<_Rs>...>;
+
+    template<typename _Ref, typename _RRef, typename _It>
+      concept __concat_indirectly_readable_impl = requires(const _It __it) {
+	{ *__it } -> convertible_to<_Ref>;
+	{ ranges::iter_move(__it) } -> convertible_to<_RRef>;
+      };
+
+    template<typename... _Rs>
+      concept __concat_indirectly_readable
+	= common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&>
+	  && common_reference_with<__concat_reference_t<_Rs...>&&,
+				   __concat_rvalue_reference_t<_Rs...>&&>
+	  && common_reference_with<__concat_rvalue_reference_t<_Rs...>&&,
+				   __concat_value_t<_Rs...> const&>
+	  && (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
+						__concat_rvalue_reference_t<_Rs...>,
+						iterator_t<_Rs>>
+	      && ...);
+
+    template<typename... _Rs>
+      concept __concatable = requires {
+	typename __concat_reference_t<_Rs...>;
+	typename __concat_value_t<_Rs...>;
+	typename __concat_rvalue_reference_t<_Rs...>;
+      } && __concat_indirectly_readable<_Rs...>;
   }
 
   template<input_range _Vp, forward_range _Pattern>
     requires view<_Vp> && view<_Pattern>
       && input_range<range_reference_t<_Vp>>
-      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern>
+      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
   class join_with_view : public view_interface<join_with_view<_Vp, _Pattern>>
   {
     using _InnerRange = range_reference_t<_Vp>;
@@ -7479,6 +7508,7 @@ namespace views::__adaptor
 	&& forward_range<const _Pattern>
 	&& is_reference_v<range_reference_t<const _Vp>>
 	&& input_range<range_reference_t<const _Vp>>
+	&& __detail::__concatable<range_reference_t<const _Vp>, const _Pattern>
     { return _Iterator<true>{*this, ranges::begin(_M_base)}; }
 
     constexpr auto
@@ -7500,6 +7530,7 @@ namespace views::__adaptor
 	&& forward_range<const _Pattern>
 	&& is_reference_v<range_reference_t<const _Vp>>
 	&& input_range<range_reference_t<const _Vp>>
+	&& __detail::__concatable<range_reference_t<const _Vp>, const _Pattern>
     {
       using _InnerConstRange = range_reference_t<const _Vp>;
       if constexpr (forward_range<_InnerConstRange>
@@ -7523,7 +7554,7 @@ namespace views::__adaptor
   template<input_range _Vp, forward_range _Pattern>
     requires view<_Vp> && view<_Pattern>
       && input_range<range_reference_t<_Vp>>
-      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern>
+      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
   template<bool _Const>
   class join_with_view<_Vp, _Pattern>::_Iterator : public __iter_cat<_Const>
   {
@@ -7812,7 +7843,7 @@ namespace views::__adaptor
   template<input_range _Vp, forward_range _Pattern>
     requires view<_Vp> && view<_Pattern>
       && input_range<range_reference_t<_Vp>>
-      && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern>
+      && __detail::__concatable<range_reference_t<_Vp>, _Pattern>
   template<bool _Const>
   class join_with_view<_Vp, _Pattern>::_Sentinel
   {
@@ -9791,41 +9822,6 @@ namespace ranges
 {
   namespace __detail
   {
-    template<typename... _Rs>
-      using __concat_reference_t = common_reference_t<range_reference_t<_Rs>...>;
-
-    template<typename... _Rs>
-      using __concat_value_t = common_type_t<range_value_t<_Rs>...>;
-
-    template<typename... _Rs>
-      using __concat_rvalue_reference_t
-	= common_reference_t<range_rvalue_reference_t<_Rs>...>;
-
-    template<typename _Ref, typename _RRef, typename _It>
-      concept __concat_indirectly_readable_impl = requires(const _It __it) {
-	{ *__it } -> convertible_to<_Ref>;
-	{ ranges::iter_move(__it) } -> convertible_to<_RRef>;
-      };
-
-    template<typename... _Rs>
-      concept __concat_indirectly_readable
-	= common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&>
-	  && common_reference_with<__concat_reference_t<_Rs...>&&,
-				   __concat_rvalue_reference_t<_Rs...>&&>
-	  && common_reference_with<__concat_rvalue_reference_t<_Rs...>&&,
-				   __concat_value_t<_Rs...> const&>
-	  && (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
-						__concat_rvalue_reference_t<_Rs...>,
-						iterator_t<_Rs>>
-	      && ...);
-
-    template<typename... _Rs>
-      concept __concatable = requires {
-	typename __concat_reference_t<_Rs...>;
-	typename __concat_value_t<_Rs...>;
-	typename __concat_rvalue_reference_t<_Rs...>;
-      } && __concat_indirectly_readable<_Rs...>;
-
     template<bool _Const, typename _Range, typename... _Rs>
       struct __all_but_last_common
       {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.