[gcc r16-8390] libstdc++/ranges: Inline hidden friends' member function helpers
Patrick Palka
ppalka@gcc.gnu.org
Wed Apr 1 15:35:14 GMT 2026
https://gcc.gnu.org/g:6497b8530c917e2877eb7853f03c7ca64c99c5cb
commit r16-8390-g6497b8530c917e2877eb7853f03c7ca64c99c5cb
Author: Patrick Palka <ppalka@redhat.com>
Date: Wed Apr 1 11:34:27 2026 -0400
libstdc++/ranges: Inline hidden friends' member function helpers
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 rely on this
relaxed interpretation. (Note that Clang also has this relaxed
interpretation, but MSVC / EDG seem to have the strict interpretation.)
This patch removes these now redundant member functions and inlines
their logic directly into the respective friend operators, making
things simpler and more consistent.
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.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Diff:
---
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 249cc466db4f..eebb978221f1 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;
@@ -2246,16 +2234,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:
@@ -2282,21 +2260,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>;
};
@@ -3300,11 +3278,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:
@@ -3326,7 +3299,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>;
};
@@ -3501,10 +3474,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
@@ -3657,7 +3626,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>;
@@ -4050,10 +4022,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;
@@ -4064,7 +4032,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; }
};
};
@@ -4671,16 +4639,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>();
@@ -4708,21 +4666,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>;
};
More information about the Libstdc++-cvs
mailing list