diff options
author | Patrick Palka <ppalka@redhat.com> | 2023-04-14 10:32:12 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2023-04-14 10:32:12 -0400 |
commit | 0d94c6df183375caaa7f672e288a2094ca813749 (patch) | |
tree | 0d5f5f1c1a656b0632467f560cb721e65298b112 /libstdc++-v3/include/std | |
parent | 2ab0d83e8880fe747af3f137aef382d2d4c09e4c (diff) | |
download | gcc-0d94c6df183375caaa7f672e288a2094ca813749.zip gcc-0d94c6df183375caaa7f672e288a2094ca813749.tar.gz gcc-0d94c6df183375caaa7f672e288a2094ca813749.tar.bz2 |
libstdc++: Implement P2278R4 "cbegin should always return a constant iterator"
This also implements the approved follow-up LWG issues 3765, 3766, 3769,
3770, 3811, 3850, 3853, 3862 and 3872.
libstdc++-v3/ChangeLog:
* include/bits/ranges_base.h (const_iterator_t): Define for C++23.
(const_sentinel_t): Likewise.
(range_const_reference_t): Likewise.
(constant_range): Likewise.
(__cust_access::__possibly_const_range): Likewise, replacing ...
(__cust_access::__as_const): ... this.
(__cust_access::_CBegin::operator()): Redefine for C++23 as per P2278R4.
(__cust_access::_CEnd::operator()): Likewise.
(__cust_access::_CRBegin::operator()): Likewise.
(__cust_access::_CREnd::operator()): Likewise.
(__cust_access::_CData::operator()): Likewise.
* include/bits/ranges_util.h (ranges::__detail::__different_from):
Make it an alias of std::__detail::__different_from.
(view_interface::cbegin): Define for C++23.
(view_interface::cend): Likewise.
* include/bits/stl_iterator.h (__detail::__different_from): Define.
(iter_const_reference_t): Define for C++23.
(__detail::__constant_iterator): Likewise.
(__detail::__is_const_iterator): Likewise.
(__detail::__not_a_const_iterator): Likewise.
(__detail::__iter_const_rvalue_reference_t): Likewise.
(__detail::__basic_const_iter_cat):: Likewise.
(const_iterator): Likewise.
(__detail::__const_sentinel): Likewise.
(const_sentinel): Likewise.
(basic_const_iterator): Likewise.
(common_type<basic_const_iterator<_Tp>, _Up>): Likewise.
(common_type<_Up, basic_const_iterator<_Tp>>): Likewise.
(common_type<basic_const_iterator<_Tp>, basic_const_iterator<Up>>):
Likewise.
(make_const_iterator): Define for C++23.
(make_const_sentinel): Likewise.
* include/std/ranges (__cpp_lib_ranges_as_const): Likewise.
(as_const_view): Likewise.
(enable_borrowed_range<as_const_view>): Likewise.
(views::__detail::__is_ref_view): Likewise.
(views::__detail::__can_is_const_view): Likewise.
(views::_AsConst, views::as_const): Likewise.
* include/std/span (span::const_iterator): Likewise.
(span::const_reverse_iterator): Likewise.
(span::cbegin): Likewise.
(span::cend): Likewise.
(span::crbegin): Likewise.
(span::crend): Likewise.
* include/std/version (__cpp_lib_ranges_as_const): Likewise.
* testsuite/std/ranges/adaptors/join.cc (test06): Adjust to
behave independently of C++20 vs C++23.
* testsuite/std/ranges/version_c++23.cc: Verify value of
__cpp_lib_ranges_as_const macro.
* testsuite/24_iterators/const_iterator/1.cc: New test.
* testsuite/std/ranges/adaptors/as_const/1.cc: New test.
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/ranges | 106 | ||||
-rw-r--r-- | libstdc++-v3/include/std/span | 22 | ||||
-rw-r--r-- | libstdc++-v3/include/std/version | 1 |
3 files changed, 129 insertions, 0 deletions
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 3f6ff50..283d757 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -8929,6 +8929,112 @@ namespace views::__adaptor inline constexpr _Enumerate enumerate; } + +#define __cpp_lib_ranges_as_const 202207L + + template<view _Vp> + requires input_range<_Vp> + class as_const_view : public view_interface<as_const_view<_Vp>> + { + _Vp _M_base = _Vp(); + + public: + as_const_view() requires default_initializable<_Vp> = default; + + constexpr explicit + as_const_view(_Vp __base) + noexcept(is_nothrow_move_constructible_v<_Vp>) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const & + noexcept(is_nothrow_copy_constructible_v<_Vp>) + requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + noexcept(is_nothrow_move_constructible_v<_Vp>) + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::cbegin(_M_base); } + + constexpr auto + begin() const requires range<const _Vp> + { return ranges::cbegin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::cend(_M_base); } + + constexpr auto + end() const requires range<const _Vp> + { return ranges::cend(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range<const _Vp> + { return ranges::size(_M_base); } + }; + + template<typename _Range> + as_const_view(_Range&&) -> as_const_view<views::all_t<_Range>>; + + template<typename _Tp> + inline constexpr bool enable_borrowed_range<as_const_view<_Tp>> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template<typename _Tp> + inline constexpr bool __is_ref_view = false; + + template<typename _Range> + inline constexpr bool __is_ref_view<ref_view<_Range>> = true; + + template<typename _Range> + concept __can_as_const_view = requires { as_const_view(std::declval<_Range>()); }; + } + + struct _AsConst : __adaptor::_RangeAdaptorClosure + { + template<viewable_range _Range> + constexpr auto + operator()(_Range&& __r) const + noexcept(noexcept(as_const_view(std::declval<_Range>()))) + requires __detail::__can_as_const_view<_Range> + { + using _Tp = remove_cvref_t<_Range>; + using element_type = remove_reference_t<range_reference_t<_Range>>; + if constexpr (constant_range<views::all_t<_Range>>) + return views::all(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_empty_view<_Tp>) + return views::empty<const element_type>; + else if constexpr (std::__detail::__is_span<_Tp>) + return span<const element_type, _Tp::extent>(std::forward<_Range>(__r)); + else if constexpr (__detail::__is_ref_view<_Tp> + && constant_range<const element_type>) + return ref_view(static_cast<const element_type&> + (std::forward<_Range>(__r).base())); + else if constexpr (is_lvalue_reference_v<_Range> + && constant_range<_Tp> + && !view<_Tp>) + return ref_view(static_cast<const _Tp&>(__r)); + else + return as_const_view(std::forward<_Range>(__r)); + } + }; + + inline constexpr _AsConst as_const; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 06d5c18..6763389 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -137,6 +137,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using const_reference = const element_type&; using iterator = __gnu_cxx::__normal_iterator<pointer, span>; using reverse_iterator = std::reverse_iterator<iterator>; +#if __cplusplus > 202002L + using const_iterator = std::const_iterator<iterator>; + using const_reverse_iterator = std::const_iterator<reverse_iterator>; +#endif // member constants static constexpr size_t extent = _Extent; @@ -301,6 +305,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION rend() const noexcept { return reverse_iterator(this->begin()); } +#if __cplusplus > 202002L + constexpr const_iterator + cbegin() const noexcept + { return begin(); } + + constexpr const_iterator + cend() const noexcept + { return end(); } + + constexpr const_reverse_iterator + crbegin() const noexcept + { return rbegin(); } + + constexpr const_reverse_iterator + crend() const noexcept + { return rend(); } +#endif + // subviews template<size_t _Count> diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index d233b03..9f31f25 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -339,6 +339,7 @@ #define __cpp_lib_ranges_stride 202207L #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_as_const 202207L #define __cpp_lib_ranges_enumerate 202302L #define __cpp_lib_fold 202207L #if __cpp_constexpr_dynamic_alloc |