[PATCH v1] libstdc++: separate std::ranges::subrange declarations from ranges_util.h

yuao via Sourceware Forge forge-bot+yuao@forge-stage.sourceware.org
Tue Sep 29 14:24:46 GMT 2026


From: Yuao Ma <c8ef@outlook.com>

gcc/testsuite/ChangeLog:

	* g++.dg/modules/inst-8_a.C: Include <new> for placement new,
	previously included transitively via <tuple>.

libstdc++-v3/ChangeLog:

	* include/Makefile.am: Regenerate.
	* include/Makefile.in: Add subrangefwd.h.
	* include/bits/ranges_util.h: Include <bits/subrangefwd.h>.
	(subrange_kind): Move to <bits/subrangefwd.h>.
	(subrange): Remove default template arguments, now on the
	declaration in <bits/subrangefwd.h>.
	(get): Use non-deduced return type.
	(__is_subrange, __is_tuple_like_v, tuple_size, tuple_element):
	Move specializations for subrange to <bits/subrangefwd.h>.
	* include/std/tuple: Include <bits/subrangefwd.h> instead of
	<bits/ranges_util.h>.
	* include/bits/subrangefwd.h: New file.
---
```
gcc/testsuite/ChangeLog:

	* g++.dg/modules/inst-8_a.C: Include <new> for placement new,
	previously included transitively via <tuple>.

libstdc++-v3/ChangeLog:

	* include/Makefile.am: Regenerate.
	* include/Makefile.in: Add subrangefwd.h.
	* include/bits/ranges_util.h: Include <bits/subrangefwd.h>.
	(subrange_kind): Move to <bits/subrangefwd.h>.
	(subrange): Remove default template arguments, now on the
	declaration in <bits/subrangefwd.h>.
	(get): Use non-deduced return type.
	(__is_subrange, __is_tuple_like_v, tuple_size, tuple_element):
	Move specializations for subrange to <bits/subrangefwd.h>.
	* include/std/tuple: Include <bits/subrangefwd.h> instead of
	<bits/ranges_util.h>.
	* include/bits/subrangefwd.h: New file.
```



This is a forge pull request published on the gcc-patches mailing list mailing list
as requested by yuao via Sourceware Forge <forge-bot+yuao@forge-stage.sourceware.org>.
Forge discussion: https://forge.sourceware.org/gcc/gcc/pulls/235

Get it locally using:
```
git fetch forge-upstream "+refs/versioned_pull/235/*:refs/versioned_pull/235/*"
git switch -c "pr-235-v1" "refs/versioned_pull/235/1/head"
```
Or, download the patch at: https://forge.sourceware.org/gcc/gcc/pulls/235.diff
Created on: 2026-09-29 14:23:56+00:00
Latest update: 2026-09-29 14:24:46+00:00
Changes: 6 changed files, 118 additions, 42 deletions
Head revision: yuao/gcc ref tuple-range commit 23d9f6413438e344cd93346f74f3eb3ffd81c36f 
Base revision: gcc/gcc ref trunk commit db655b1fdce54adaf3d983ad73dd02db6cbdedf8 r17-4418-gdb655b1fdce54a
Merge base: db655b1fdce54adaf3d983ad73dd02db6cbdedf8
Requested Reviewers: redi

Changed files:
- A: libstdc++-v3/include/bits/subrangefwd.h
- M: gcc/testsuite/g++.dg/modules/inst-8_a.C
- M: libstdc++-v3/include/Makefile.am
- M: libstdc++-v3/include/Makefile.in
- M: libstdc++-v3/include/bits/ranges_util.h
- M: libstdc++-v3/include/std/tuple

 gcc/testsuite/g++.dg/modules/inst-8_a.C |   1 +
 libstdc++-v3/include/Makefile.am        |   1 +
 libstdc++-v3/include/Makefile.in        |   1 +
 libstdc++-v3/include/bits/ranges_util.h |  46 ++--------
 libstdc++-v3/include/bits/subrangefwd.h | 109 ++++++++++++++++++++++++
 libstdc++-v3/include/std/tuple          |   2 +-
 6 files changed, 118 insertions(+), 42 deletions(-)
 create mode 100644 libstdc++-v3/include/bits/subrangefwd.h

diff --git a/gcc/testsuite/g++.dg/modules/inst-8_a.C b/gcc/testsuite/g++.dg/modules/inst-8_a.C
index 1b0a47978cb2d..da8afd35beab7 100644
--- a/gcc/testsuite/g++.dg/modules/inst-8_a.C
+++ b/gcc/testsuite/g++.dg/modules/inst-8_a.C
@@ -5,6 +5,7 @@
 
 module;
 #include <coroutine>
+#include <new>
 #include <tuple>
 #include <typeinfo>
 export module std;
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 3c30aa21d6b55..ebdb3410df15f 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -185,6 +185,7 @@ bits_freestanding = \
 	${bits_srcdir}/stl_raw_storage_iter.h \
 	${bits_srcdir}/stl_relops.h \
 	${bits_srcdir}/stl_uninitialized.h \
+	${bits_srcdir}/subrangefwd.h \
 	${bits_srcdir}/text_encoding-data.h \
 	${bits_srcdir}/version.h \
 	${bits_srcdir}/string_view.tcc \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index d081481293fff..333d17cb6c154 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -543,6 +543,7 @@ bits_freestanding = \
 	${bits_srcdir}/stl_raw_storage_iter.h \
 	${bits_srcdir}/stl_relops.h \
 	${bits_srcdir}/stl_uninitialized.h \
+	${bits_srcdir}/subrangefwd.h \
 	${bits_srcdir}/text_encoding-data.h \
 	${bits_srcdir}/version.h \
 	${bits_srcdir}/string_view.tcc \
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index 423767f00fcb6..6f78c6c460a78 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -35,6 +35,7 @@
 # include <bits/utility.h>
 # include <bits/invoke.h>
 # include <bits/cpp_type_traits.h> // __can_use_memchr_for_find
+# include <bits/subrangefwd.h>     // subrange, get, tuple_size
 #if __glibcxx_tuple_like // >= C++23
 # include <bits/stl_pair.h> // __pair_like, __is_tuple_like_v
 #endif
@@ -259,12 +260,8 @@ namespace ranges
 
   namespace views { struct _Drop; } // defined in <ranges>
 
-  enum class subrange_kind : bool { unsized, sized };
-
-  /// The ranges::subrange class template
-  template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
-	   subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
-	     ? subrange_kind::sized : subrange_kind::unsized>
+  template<input_or_output_iterator _It, sentinel_for<_It> _Sent,
+	   subrange_kind _Kind>
     requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
     class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
     {
@@ -450,7 +447,7 @@ namespace ranges
   // constrain I to be copyable when N == 0
   template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
     requires ((_Num == 0 && copyable<_It>) || _Num == 1)
-    constexpr auto
+    constexpr __conditional_t<_Num == 0, _It, _Sent>
     get(const subrange<_It, _Sent, _Kind>& __r)
     {
       if constexpr (_Num == 0)
@@ -461,7 +458,7 @@ namespace ranges
 
   template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
     requires (_Num < 2)
-    constexpr auto
+    constexpr __conditional_t<_Num == 0, _It, _Sent>
     get(subrange<_It, _Sent, _Kind>&& __r)
     {
       if constexpr (_Num == 0)
@@ -478,18 +475,8 @@ namespace ranges
     using borrowed_subrange_t = __conditional_t<borrowed_range<_Range>,
 						subrange<iterator_t<_Range>>,
 						dangling>;
-
-  // __is_subrange is defined in <bits/utility.h>.
-  template<typename _Iter, typename _Sent, subrange_kind _Kind>
-    inline constexpr bool __detail::__is_subrange<subrange<_Iter, _Sent, _Kind>> = true;
 } // namespace ranges
 
-#if __glibcxx_tuple_like // >= C++23
-  // __is_tuple_like_v is defined in <bits/stl_pair.h>.
-  template<typename _It, typename _Sent, ranges::subrange_kind _Kind>
-    inline constexpr bool __is_tuple_like_v<ranges::subrange<_It, _Sent, _Kind>> = true;
-#endif
-
 // The following ranges algorithms are used by <ranges>, and are defined here
 // so that <ranges> can avoid including all of <bits/ranges_algo.h>.
 namespace ranges
@@ -827,29 +814,6 @@ namespace ranges
 
 } // namespace ranges
 
-  using ranges::get;
-
-  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
-    struct tuple_size<ranges::subrange<_Iter, _Sent, _Kind>>
-    : integral_constant<size_t, 2>
-    { };
-
-  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
-    struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>>
-    { using type = _Iter; };
-
-  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
-    struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>>
-    { using type = _Sent; };
-
-  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
-    struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>>
-    { using type = _Iter; };
-
-  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
-    struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>>
-    { using type = _Sent; };
-
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // library concepts
diff --git a/libstdc++-v3/include/bits/subrangefwd.h b/libstdc++-v3/include/bits/subrangefwd.h
new file mode 100644
index 0000000000000..2a7c83b54f5bb
--- /dev/null
+++ b/libstdc++-v3/include/bits/subrangefwd.h
@@ -0,0 +1,109 @@
+// Forward declarations for std::ranges::subrange -*- C++ -*-
+
+// Copyright (C) 2026 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/subrangefwd.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{ranges}
+ */
+
+#ifndef _SUBRANGEFWD_H
+#define _SUBRANGEFWD_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_ranges // C++ >= 20 && concepts
+#include <bits/stl_iterator_base_types.h>
+#include <bits/utility.h>
+#if __glibcxx_tuple_like // >= C++23
+# include <bits/stl_pair.h>
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace ranges
+{
+  enum class subrange_kind : bool { unsized, sized };
+
+  /// The ranges::subrange class template.
+  template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
+	   subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
+	     ? subrange_kind::sized : subrange_kind::unsized>
+    requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
+    class subrange;
+
+  template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
+    requires ((_Num == 0 && copyable<_It>) || _Num == 1)
+    constexpr __conditional_t<_Num == 0, _It, _Sent>
+    get(const subrange<_It, _Sent, _Kind>& __r);
+
+  template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
+    requires (_Num < 2)
+    constexpr __conditional_t<_Num == 0, _It, _Sent>
+    get(subrange<_It, _Sent, _Kind>&& __r);
+
+  // __is_subrange is defined in <bits/utility.h>.
+  template<typename _Iter, typename _Sent, subrange_kind _Kind>
+    inline constexpr bool
+      __detail::__is_subrange<subrange<_Iter, _Sent, _Kind>> = true;
+} // namespace ranges
+
+  using ranges::get;
+
+#if __glibcxx_tuple_like // >= C++23
+  // __is_tuple_like_v is defined in <bits/stl_pair.h>.
+  template<typename _It, typename _Sent, ranges::subrange_kind _Kind>
+    inline constexpr bool
+      __is_tuple_like_v<ranges::subrange<_It, _Sent, _Kind>> = true;
+#endif
+
+  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
+    struct tuple_size<ranges::subrange<_Iter, _Sent, _Kind>>
+    : integral_constant<size_t, 2>
+    { };
+
+  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
+    struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>>
+    { using type = _Iter; };
+
+  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
+    struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>>
+    { using type = _Sent; };
+
+  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
+    struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>>
+    { using type = _Iter; };
+
+  template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
+    struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>>
+    { using type = _Sent; };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_ranges
+#endif // _SUBRANGEFWD_H
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 63b4010c0b5e8..67be8374cf1fa 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -43,7 +43,7 @@
 #include <bits/invoke.h>		// for std::__invoke
 #if __cplusplus > 201703L
 # include <compare>
-# include <bits/ranges_util.h>		// for std::ranges::subrange
+# include <bits/subrangefwd.h>		// for std::ranges::subrange
 #endif
 
 #define __glibcxx_want_constexpr_tuple
-- 
2.54.0



More information about the Libstdc++ mailing list