[gcc r17-65] libstdc++: Constrain views::adjacent(_transform)?<0> to forward_ranges.

Tomasz Kaminski tkaminsk@gcc.gnu.org
Fri Apr 24 10:40:50 GMT 2026


https://gcc.gnu.org/g:8defa4b8b1ce23c68e681a42ba82c471c2a10bff

commit r17-65-g8defa4b8b1ce23c68e681a42ba82c471c2a10bff
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date:   Fri Apr 24 11:58:39 2026 +0200

    libstdc++: Constrain views::adjacent(_transform)?<0> to forward_ranges.
    
    This resolves LWG 4098, "views::adjacent<0> should reject non-forward ranges"
    which was approved in Sofia 2024.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/ranges (_AdjacentTransform::operator())
            (_Adjacent::operator()): Require forward_range for N == 0.
            * testsuite/std/ranges/adaptors/adjacent/1.cc: Test if input_ranges
            are rejected.
            * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: Likewise.
    
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

Diff:
---
 libstdc++-v3/include/std/ranges                                | 10 ++++++++--
 libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc       |  7 +++++++
 .../testsuite/std/ranges/adaptors/adjacent_transform/1.cc      |  7 +++++++
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 9c7d639a1543..24416b659c10 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -5859,8 +5859,11 @@ namespace views::__adaptor
     template<size_t _Nm>
       struct _Adjacent : __adaptor::_RangeAdaptorClosure<_Adjacent<_Nm>>
       {
+	// _GLIBCXX_RESOLVE_LIB_DEFECTS
+	// 4098. views::adjacent<0> should reject non-forward ranges
 	template<viewable_range _Range>
-	  requires (_Nm == 0) || __detail::__can_adjacent_view<_Nm, _Range>
+	  requires ((_Nm == 0) && forward_range<_Range>)
+		   || __detail::__can_adjacent_view<_Nm, _Range>
 	  constexpr auto
 	  operator() [[nodiscard]] (_Range&& __r) const
 	  {
@@ -6197,8 +6200,11 @@ namespace views::__adaptor
     template<size_t _Nm>
       struct _AdjacentTransform : __adaptor::_RangeAdaptor<_AdjacentTransform<_Nm>>
       {
+	// _GLIBCXX_RESOLVE_LIB_DEFECTS
+	// 4098. views::adjacent<0> should reject non-forward ranges
 	template<viewable_range _Range, typename _Fp>
-	  requires (_Nm == 0) || __detail::__can_adjacent_transform_view<_Nm, _Range, _Fp>
+	  requires ((_Nm == 0) && forward_range<_Range>)
+		   || __detail::__can_adjacent_transform_view<_Nm, _Range, _Fp>
 	  constexpr auto
 	  operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const
 	  {
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
index 0a5c67f56140..57322922e5e4 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
@@ -9,6 +9,13 @@
 namespace ranges = std::ranges;
 namespace views = std::views;
 
+template<typename Range>
+concept can_adjacent0 = requires (Range& rg)
+{ views::adjacent<0>(rg); };
+
+static_assert( !can_adjacent0<__gnu_test::test_input_range<int>> );
+static_assert( can_adjacent0<__gnu_test::test_forward_range<int>> );
+
 constexpr bool
 test01()
 {
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
index 6890618754b6..a75d02efbb8e 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
@@ -9,6 +9,13 @@
 namespace ranges = std::ranges;
 namespace views = std::views;
 
+template<typename Range>
+concept can_adjacent0 = requires (Range& rg)
+{ views::adjacent_transform<0>(rg, []() { return 10; }); };
+
+static_assert( !can_adjacent0<__gnu_test::test_input_range<int>> );
+static_assert( can_adjacent0<__gnu_test::test_forward_range<int>> );
+
 constexpr bool
 test01()
 {


More information about the Libstdc++-cvs mailing list