[PATCH 2/2] libstdc++/ranges: Inline hidden friends' member function helpers
Jonathan Wakely
jwakely@redhat.com
Tue Mar 31 19:38:39 GMT 2026
On Tue, 31 Mar 2026 at 19:43, Patrick Palka <ppalka@redhat.com> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk only?
>
> -- >8 --
>
> These helpers were needed to work around GCC's historically strict
> interpretation of friendship for hidden friends whereby they did not
> inherit the friends of the containing class. But this has been relaxed
> in r13-465 which granted hidden friends the same access as any other
> member declaration, and <ranges> additions since then commit rely on
This should be
s/since then commit/since that commit/
I assume?
OK with that change. This should give a small improvement in
compilation time, which is always welcome.
> this relaxed interpretation. (Note that Clang shares this relaxed
> inherpretation since inception, though MSVC / EDG seem to have the
> strict interpretation.)
>
> This patch removes these roundabout member functions and inlines
> their logic directly into the respective friend operators for sake
> of simplicity and consistency.
>
> libstdc++-v3/ChangeLog:
>
> * include/std/ranges (iota_view::_Sentinel): Remove _M_equal and
> _M_distance_from. Inline logic into friend operators.
> (basic_istream_view::_Iterator): Remove _M_at_end. Inline logic
> into operator==.
> (transform_view::_Sentinel): Remove __distance_from and __equal.
> Inline logic into friend operators.
> (join_view::_Sentinel): Remove __equal. Inline logic into operator==.
> (lazy_split_view::_OuterIter): Remove __at_end. Inline logic into
> operator==.
> (split_view::_Sentinel): Remove _M_equal. Inline logic into operator==.
> (elements_view::_Sentinel): Remove _M_equal and _M_distance_from.
> Inline logic into friend operators.
> ---
> libstdc++-v3/include/std/ranges | 74 +++++++--------------------------
> 1 file changed, 16 insertions(+), 58 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 80c3f922c201..a965a221f299 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -752,14 +752,6 @@ namespace ranges
> struct _Sentinel
> {
> private:
> - constexpr bool
> - _M_equal(const _Iterator& __x) const
> - { return __x._M_value == _M_bound; }
> -
> - constexpr auto
> - _M_distance_from(const _Iterator& __x) const
> - { return _M_bound - __x._M_value; }
> -
> _Bound _M_bound = _Bound();
>
> public:
> @@ -771,17 +763,17 @@ namespace ranges
>
> friend constexpr bool
> operator==(const _Iterator& __x, const _Sentinel& __y)
> - { return __y._M_equal(__x); }
> + { return __x._M_value == __y._M_bound; }
>
> friend constexpr iter_difference_t<_Winc>
> operator-(const _Iterator& __x, const _Sentinel& __y)
> requires sized_sentinel_for<_Bound, _Winc>
> - { return -__y._M_distance_from(__x); }
> + { return -(__y._M_bound - __x._M_value); }
>
> friend constexpr iter_difference_t<_Winc>
> operator-(const _Sentinel& __x, const _Iterator& __y)
> requires sized_sentinel_for<_Bound, _Winc>
> - { return __x._M_distance_from(__y); }
> + { return __x._M_bound - __y._M_value; }
>
> friend iota_view;
> };
> @@ -1006,14 +998,10 @@ namespace views
>
> friend bool
> operator==(const _Iterator& __x, default_sentinel_t)
> - { return __x._M_at_end(); }
> + { return !*__x._M_parent->_M_stream; }
>
> private:
> basic_istream_view* _M_parent;
> -
> - bool
> - _M_at_end() const
> - { return !*_M_parent->_M_stream; }
> };
>
> friend _Iterator;
> @@ -2245,16 +2233,6 @@ namespace views::__adaptor
> using _Parent = __detail::__maybe_const_t<_Const, transform_view>;
> using _Base = transform_view::_Base<_Const>;
>
> - template<bool _Const2>
> - constexpr auto
> - __distance_from(const _Iterator<_Const2>& __i) const
> - { return _M_end - __i._M_current; }
> -
> - template<bool _Const2>
> - constexpr bool
> - __equal(const _Iterator<_Const2>& __i) const
> - { return __i._M_current == _M_end; }
> -
> sentinel_t<_Base> _M_end = sentinel_t<_Base>();
>
> public:
> @@ -2281,21 +2259,21 @@ namespace views::__adaptor
> iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
> friend constexpr bool
> operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
> - { return __y.__equal(__x); }
> + { return __x._M_current == __y._M_end; }
>
> template<bool _Const2,
> typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
> friend constexpr range_difference_t<_Base2>
> operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y)
> - { return -__y.__distance_from(__x); }
> + { return -(__y._M_end - __x._M_current); }
>
> template<bool _Const2,
> typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
> friend constexpr range_difference_t<_Base2>
> operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x)
> - { return __y.__distance_from(__x); }
> + { return __y._M_end - __x._M_current; }
>
> friend _Sentinel<!_Const>;
> };
> @@ -3299,11 +3277,6 @@ namespace views::__adaptor
> using _Parent = __detail::__maybe_const_t<_Const, join_view>;
> using _Base = join_view::_Base<_Const>;
>
> - template<bool _Const2>
> - constexpr bool
> - __equal(const _Iterator<_Const2>& __i) const
> - { return __i._M_get_outer() == _M_end; }
> -
> sentinel_t<_Base> _M_end = sentinel_t<_Base>();
>
> public:
> @@ -3325,7 +3298,7 @@ namespace views::__adaptor
> iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
> friend constexpr bool
> operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
> - { return __y.__equal(__x); }
> + { return __x._M_get_outer() == __y._M_end; }
>
> friend _Sentinel<!_Const>;
> };
> @@ -3500,10 +3473,6 @@ namespace views::__adaptor
> using _Parent = __detail::__maybe_const_t<_Const, lazy_split_view>;
> using _Base = lazy_split_view::_Base<_Const>;
>
> - constexpr bool
> - __at_end() const
> - { return __current() == ranges::end(_M_parent->_M_base) && !_M_trailing_empty; }
> -
> // [range.lazy.split.outer] p1
> // Many of the following specifications refer to the notional member
> // current of outer-iterator. current is equivalent to current_ if
> @@ -3656,7 +3625,10 @@ namespace views::__adaptor
>
> friend constexpr bool
> operator==(const _OuterIter& __x, default_sentinel_t)
> - { return __x.__at_end(); };
> + {
> + return __x.__current() == ranges::end(__x._M_parent->_M_base)
> + && !__x._M_trailing_empty;
> + }
>
> friend _OuterIter<!_Const>;
> friend _InnerIter<_Const>;
> @@ -4049,10 +4021,6 @@ namespace views::__adaptor
> private:
> sentinel_t<_Vp> _M_end = sentinel_t<_Vp>();
>
> - constexpr bool
> - _M_equal(const _Iterator& __x) const
> - { return __x._M_cur == _M_end && !__x._M_trailing_empty; }
> -
> public:
> _Sentinel() = default;
>
> @@ -4063,7 +4031,7 @@ namespace views::__adaptor
>
> friend constexpr bool
> operator==(const _Iterator& __x, const _Sentinel& __y)
> - { return __y._M_equal(__x); }
> + { return __x._M_cur == __y._M_end && !__x._M_trailing_empty; }
> };
> };
>
> @@ -4670,16 +4638,6 @@ namespace views::__adaptor
> struct _Sentinel
> {
> private:
> - template<bool _Const2>
> - constexpr bool
> - _M_equal(const _Iterator<_Const2>& __x) const
> - { return __x._M_current == _M_end; }
> -
> - template<bool _Const2>
> - constexpr auto
> - _M_distance_from(const _Iterator<_Const2>& __i) const
> - { return _M_end - __i._M_current; }
> -
> using _Base = elements_view::_Base<_Const>;
> sentinel_t<_Base> _M_end = sentinel_t<_Base>();
>
> @@ -4707,21 +4665,21 @@ namespace views::__adaptor
> iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
> friend constexpr bool
> operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
> - { return __y._M_equal(__x); }
> + { return __x._M_current == __y._M_end; }
>
> template<bool _Const2,
> typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
> friend constexpr range_difference_t<_Base2>
> operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y)
> - { return -__y._M_distance_from(__x); }
> + { return -(__y._M_end - __x._M_current); }
>
> template<bool _Const2,
> typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
> friend constexpr range_difference_t<_Base2>
> operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y)
> - { return __x._M_distance_from(__y); }
> + { return __x._M_end - __y._M_current; }
>
> friend _Sentinel<!_Const>;
> };
> --
> 2.53.0.764.g270e10ad6d
>
More information about the Libstdc++
mailing list