Some of the range adaptors have distinct constant and non-constant
iterator/sentinel types, along with converting constructors that can convert a
non-constant iterator/sentinel to a constant iterator/sentinel. This patch adds
the missing appropriate friend declarations in order to make these converting
constructors well formed.
Strictly speaking it seems the friendship relation doesn't need to go both ways
-- we could get away with declaring e.g. friend _Iterator; instead of
friend _Iterator; but the spec and the reference implementations all
seem to use the latter symmetric form anyway.
libstdc++-v3/ChangeLog:
* include/std/ranges (transform_view::_Iterator<_Const>): Befriend
_Iterator.
(transform_view::_Sentinel<_Const>): Befriend _Sentinel.
(take_view::_Sentinel<_Const>): Likewise.
(take_while_view::_Sentinel<_Const>): Likewise.
(split_view::_OuterIter<_Const>): Befriend _OuterIter.
* std/ranges/adaptors/split.cc: Augment test.
* std/ranges/adaptors/take.cc: Augment test.
* std/ranges/adaptors/take_while.cc: Augment test.
* std/ranges/adaptors/transform.cc: Augment test.
---
libstdc++-v3/include/std/ranges | 8 +++
.../testsuite/std/ranges/adaptors/split.cc| 14 +++
.../testsuite/std/ranges/adaptors/take.cc | 16 +
.../std/ranges/adaptors/take_while.cc | 17 ++
.../std/ranges/adaptors/transform.cc | 23 +++
5 files changed, 78 insertions(+)
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 2e3e298adcc..2f08cfd7f16 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1844,6 +1844,7 @@ namespace views
requires indirectly_swappable<_Base_iter>
{ return ranges::iter_swap(__x._M_current, __y._M_current); }
+ friend _Iterator;
friend _Sentinel<_Const>;
};
@@ -1896,6 +1897,8 @@ namespace views
operator-(const _Sentinel& __y, const _Iterator<_Const>& __x)
requires sized_sentinel_for, iterator_t<_Base>>
{ return __y.__distance_from(__x); }
+
+ friend _Sentinel;
};
_Vp _M_base = _Vp();
@@ -2001,6 +2004,8 @@ namespace views
friend constexpr bool operator==(const _CI& __y, const _Sentinel& __x)
{ return __y.count() == 0 || __y.base() == __x._M_end; }
+
+ friend _Sentinel;
};
_Vp _M_base = _Vp();
@@ -2140,6 +2145,8 @@ namespace views
friend constexpr bool
operator==(const iterator_t<_Base>& __x, const _Sentinel& __y)
{ return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); }
+
+ friend _Sentinel;
};
_Vp _M_base = _Vp();
@@ -2831,6 +2838,7 @@ namespace views
operator==(const _OuterIter& __x, default_sentinel_t)
{ return __x.__at_end(); };
+ friend _OuterIter;
friend _InnerIter<_Const>;
};
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
index 52b015cf0c6..e7556725e4f 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
@@ -108,6 +108,19 @@ test05()
str | views::filter(not_space_p)) );
}
+void
+test06()
+{
+ std::string str = "hello world";
+ auto v = str | views::transform(std::identity{}) | views::split(' ');
+
+ // Verify that _Iterator is implicitly convertible to _Iterator.
+ static_assert(!std::same_as);
+ auto b = ranges::cbegin(v);
+ b = ranges::begin(v);
+}
+
int
main()
{
@@ -116,4 +129,5 @@ main()
test03();
test04();
test05();
+ test06();
}
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
index e2d2edbe0a8..c42505b44cb 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
@@ -19,6 +19,7 @@
// { dg-do run { target c++2a } }
#include
+#include
#include
#include
#include
@@ -85,6 +86,20 @@ test04()
VERIFY( ranges::equal(v | views::take(5), (int[]){1,2,3}) );
}
+void
+test05()
+{
+ std::forward_list x = {1,2,3,4,5};
+ auto v = x | views::transform(std::negate{}) | views::take(4);
+
+ // Verify that _Sentinel is implicitly convertible to _Sentinel.
+ static_assert(!ranges::common_range);
+ static_assert(!std::same_as);
+ auto b = ranges::cend(v);
+ b = ranges::end(v);
+}
+
int
main()
{
@@ -92,4 +107,5 @@ main()
test02();
test03();
test04();
+ test05();
}
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
b/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
index b261ffd1aae..d587127b97e 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
@@