[PATCH] libstdc++: Constrain views::adjacent(_transform)?<0> to forward_ranges.

Jonathan Wakely jwakely@redhat.com
Fri Apr 24 10:27:21 GMT 2026


On Fri, 24 Apr 2026 at 11:11, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Fri, 24 Apr 2026 at 11:05, Tomasz Kamiński <tkaminsk@redhat.com> wrote:
> >
> > 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.
> > ---
> > Testing on x86_64-linux. *adaptors/adjacent* test passed.
> > OK for trunk when all tests passes?
> >
> >  libstdc++-v3/include/std/ranges                        | 10 ++++++++--
> >  .../testsuite/std/ranges/adaptors/adjacent/1.cc        |  7 +++++++
> >  .../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 9c7d639a154..ba4c9f60ab2 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>
>
> Please add parentheses around these to make the operator precedence clear.

OK with that change (in both places).

>
> > +                  || __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 0a5c67f5614..57322922e5e 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 6890618754b..a75d02efbb8 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()
> >  {
> > --
> > 2.53.0
> >



More information about the Libstdc++ mailing list