Tested on x86_64-pc-linux-gnu, does this look OK for trunk/15/14?
-- >8 --
LWG 3946 made const_iterator/sentinel_t get defined directly in terms of
ranges::cbegin/cend, but I defined it the other way around in an incorrect
way that made the aliases not consider __possibly_const_range. This patch
reimplements the proposed resolution in a more obviously correct way,
mirroring the wording.
PR libstdc++/122842
libstdc++-v3/ChangeLog:
* include/bits/ranges_base.h (__access:_CBegin): Define in
terms of const_iterator directly, not const_iterator_t.
(__access::_CEnd): Likewise in terms of const_sentinel vs
const_sentinel_t.
(const_iterator_t): Move down definition and define in terms
of ranges::cbegin as per LWG 3946.
(const_sentinel_t): Likewise in terms of ranges::cend.
* testsuite/24_iterators/const_iterator/1.cc (test02): Adjust
test for int[], std::array and std::vector. Also test
std::string.
---
libstdc++-v3/include/bits/ranges_base.h | 20 ++++++++----
.../24_iterators/const_iterator/1.cc | 32 +++++++++++++------
2 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/libstdc++-v3/include/bits/ranges_base.h
b/libstdc++-v3/include/bits/ranges_base.h
index 1c4bf432c8f4..0b8151cd65dd 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -525,11 +525,7 @@ namespace ranges
using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
#if __glibcxx_ranges_as_const // >= C++23
- template<range _Range>
- using const_iterator_t = const_iterator<iterator_t<_Range>>;
-
- template<range _Range>
- using const_sentinel_t = const_sentinel<sentinel_t<_Range>>;
+ // const_iterator_t and const_sentinel_t defined below.
template<range _Range>
using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>;
@@ -683,7 +679,7 @@ namespace ranges
(ranges::begin(__access::__possibly_const_range(__t))); }
{
auto& __r = __access::__possibly_const_range(__t);
- return const_iterator_t<decltype(__r)>(ranges::begin(__r));
+ return
const_iterator<decltype(ranges::begin(__r))>(ranges::begin(__r));
}
#else
template<typename _Tp>
@@ -711,7 +707,7 @@ namespace ranges
(ranges::end(__access::__possibly_const_range(__t))); }
{
auto& __r = __access::__possibly_const_range(__t);
- return const_sentinel_t<decltype(__r)>(ranges::end(__r));
+ return const_sentinel<decltype(ranges::end(__r))>(ranges::end(__r));
}
#else
template<typename _Tp>
@@ -815,6 +811,16 @@ namespace ranges
inline constexpr ranges::__access::_CData cdata{};
}
+#if __glibcxx_ranges_as_const // >= C++23
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3946. The definition of const_iterator_t should be reworked
+ template<range _Range>
+ using const_iterator_t = decltype(ranges::cbegin(std::declval<_Range&>()));
+
+ template<range _Range>
+ using const_sentinel_t = decltype(ranges::cend(std::declval<_Range&>()));
+#endif
+
namespace __detail
{
template<typename _Tp>
diff --git a/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
b/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
index fe952bfad148..63905e9d63d8 100644
--- a/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
+++ b/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
@@ -42,12 +42,13 @@ test01()
}
}
-template<class Range, bool Const>
+template<class Range, bool Const, bool Constable = Const>
void
test02()
{
if constexpr (Const)
{
+ static_assert(Constable);
static_assert( ranges::constant_range<Range> );
static_assert( std::same_as<ranges::const_iterator_t<Range>,
ranges::iterator_t<Range>> );
static_assert( std::same_as<ranges::const_sentinel_t<Range>,
ranges::sentinel_t<Range>> );
@@ -64,11 +65,22 @@ test02()
static_assert( !ranges::constant_range<Range> );
using Wrapped = std::basic_const_iterator<ranges::iterator_t<Range>>;
- static_assert( std::same_as<ranges::const_iterator_t<Range>, Wrapped> );
- if constexpr (ranges::common_range<Range>)
- static_assert( std::same_as<ranges::const_sentinel_t<Range>, Wrapped> );
- static_assert( std::same_as<ranges::range_const_reference_t<Range>,
- std::iter_reference_t<Wrapped>> );
+ if constexpr (Constable)
+ {
+ // Verify LWG 3946 changes to const_iterator/sentinel_t (PR122842).
+ static_assert( std::same_as<ranges::const_iterator_t<Range>,
+ ranges::iterator_t<const Range>> );
+ static_assert( std::same_as<ranges::const_sentinel_t<Range>,
+ ranges::sentinel_t<const Range>> );
+ }
+ else
+ {
+ static_assert( std::same_as<ranges::const_iterator_t<Range>, Wrapped>
);
+ if constexpr (ranges::common_range<Range>)
+ static_assert( std::same_as<ranges::const_sentinel_t<Range>,
Wrapped> );
+ static_assert( std::same_as<ranges::range_const_reference_t<Range>,
+ std::iter_reference_t<Wrapped>> );
+ }
static_assert( ranges::input_range<Range> ==
std::input_iterator<Wrapped> );
static_assert( ranges::forward_range<Range> ==
std::forward_iterator<Wrapped> );
@@ -138,13 +150,14 @@ main()
test01<std::string_view::iterator, true>();
test01<std::vector<bool>::const_iterator, true>();
- test02<int[42], false>();
+ test02<int[42], false, true>();
test02<test_input_range<int>, false>();
test02<test_forward_range<int>, false>();
test02<test_bidirectional_range<int>, false>();
test02<test_random_access_range<int>, false>();
- test02<std::array<int, 3>, false>();
- test02<std::vector<bool>, false>();
+ test02<std::array<int, 3>, false, true>();
+ test02<std::vector<bool>, false, true>();
+ test02<std::string, false, true>();
test02<const int[42], true>();
test02<test_input_range<const int>, true>();
@@ -155,6 +168,7 @@ main()
test02<const std::array<int, 3>, true>();
test02<std::string_view, true>();
test02<const std::vector<bool>, true>();
+ test02<const std::string, true>();
test03();
test04();
--
2.52.0.84.g6ab38b7e9c