|
| 1 | +// -*- C++ -*- |
| 2 | +//===----------------------------------------------------------------------===// |
| 3 | +// |
| 4 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | +// See https://llvm.org/LICENSE.txt for license information. |
| 6 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 7 | +// |
| 8 | +//===----------------------------------------------------------------------===// |
| 9 | + |
| 10 | +#ifndef _LIBCPP___RANGES_AS_CONST_VIEW_H |
| 11 | +#define _LIBCPP___RANGES_AS_CONST_VIEW_H |
| 12 | + |
| 13 | +#include <__concepts/constructible.h> |
| 14 | +#include <__iterator/concepts.h> |
| 15 | +#include <__ranges/all.h> |
| 16 | +#include <__ranges/concepts.h> |
| 17 | +#include <__ranges/const_access.h> |
| 18 | +#include <__ranges/empty_view.h> |
| 19 | +#include <__ranges/range_adaptor.h> |
| 20 | +#include <__ranges/size.h> |
| 21 | +#include <__ranges/view_interface.h> |
| 22 | +#include <__type_traits/is_specialization.h> |
| 23 | +#include <__utility/auto_cast.h> |
| 24 | +#include <__utility/move.h> |
| 25 | +#include <cstddef> |
| 26 | +#include <span> |
| 27 | + |
| 28 | +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 29 | +# pragma GCC system_header |
| 30 | +#endif |
| 31 | + |
| 32 | +_LIBCPP_PUSH_MACROS |
| 33 | +#include <__undef_macros> |
| 34 | + |
| 35 | +_LIBCPP_BEGIN_NAMESPACE_STD |
| 36 | + |
| 37 | +#if _LIBCPP_STD_VER >= 23 |
| 38 | + |
| 39 | +namespace ranges { |
| 40 | +template <input_range _View> |
| 41 | + requires view<_View> |
| 42 | +class as_const_view : public view_interface<as_const_view<_View>> { |
| 43 | + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); |
| 44 | + |
| 45 | +public: |
| 46 | + _LIBCPP_HIDE_FROM_ABI as_const_view() |
| 47 | + requires default_initializable<_View> |
| 48 | + = default; |
| 49 | + _LIBCPP_HIDE_FROM_ABI constexpr explicit as_const_view(_View __base) : __base_(std::move(__base)) {} |
| 50 | + |
| 51 | + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& |
| 52 | + requires copy_constructible<_View> |
| 53 | + { |
| 54 | + return __base_; |
| 55 | + } |
| 56 | + |
| 57 | + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } |
| 58 | + |
| 59 | + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() |
| 60 | + requires(!__simple_view<_View>) |
| 61 | + { |
| 62 | + return ranges::cbegin(__base_); |
| 63 | + } |
| 64 | + |
| 65 | + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const |
| 66 | + requires range<const _View> |
| 67 | + { |
| 68 | + return ranges::cbegin(__base_); |
| 69 | + } |
| 70 | + |
| 71 | + _LIBCPP_HIDE_FROM_ABI constexpr auto end() |
| 72 | + requires(!__simple_view<_View>) |
| 73 | + { |
| 74 | + return ranges::cend(__base_); |
| 75 | + } |
| 76 | + |
| 77 | + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const |
| 78 | + requires range<const _View> |
| 79 | + { |
| 80 | + return ranges::cend(__base_); |
| 81 | + } |
| 82 | + |
| 83 | + _LIBCPP_HIDE_FROM_ABI constexpr auto size() |
| 84 | + requires sized_range<_View> |
| 85 | + { |
| 86 | + return ranges::size(__base_); |
| 87 | + } |
| 88 | + |
| 89 | + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const |
| 90 | + requires sized_range<const _View> |
| 91 | + { |
| 92 | + return ranges::size(__base_); |
| 93 | + } |
| 94 | +}; |
| 95 | + |
| 96 | +template <class _Range> |
| 97 | +as_const_view(_Range&&) -> as_const_view<views::all_t<_Range>>; |
| 98 | + |
| 99 | +template <class _Tp> |
| 100 | +inline constexpr bool enable_borrowed_range<as_const_view<_Tp>> = enable_borrowed_range<_Tp>; |
| 101 | + |
| 102 | +namespace views { |
| 103 | +namespace __as_const { |
| 104 | + |
| 105 | +template <class _Tp> |
| 106 | +concept __has_type = requires { typename _Tp::type; }; |
| 107 | + |
| 108 | +template <class _Tp> |
| 109 | +struct __empty_view_case {}; |
| 110 | +template <class _Tp> |
| 111 | +struct __empty_view_case<empty_view<_Tp>> { |
| 112 | + using type = const _Tp; |
| 113 | +}; |
| 114 | + |
| 115 | +template <class _Tp> |
| 116 | +struct __span_case {}; |
| 117 | +template <class _Tp, size_t _Extent> |
| 118 | +struct __span_case<span<_Tp, _Extent>> { |
| 119 | + using type = span<const _Tp, _Extent>; |
| 120 | +}; |
| 121 | + |
| 122 | +template <class _Tp> |
| 123 | +struct __ref_view_case {}; |
| 124 | +template <class _Tp> |
| 125 | + requires constant_range<const _Tp> |
| 126 | +struct __ref_view_case<ref_view<_Tp>> { |
| 127 | + using type = const _Tp&; |
| 128 | +}; |
| 129 | + |
| 130 | +template <class _Tp> |
| 131 | +struct __constant_range_case {}; |
| 132 | +template <class _Tp> |
| 133 | + requires constant_range<const _Tp> && (!view<_Tp>) |
| 134 | +struct __constant_range_case<_Tp> { |
| 135 | + using type = const _Tp&; |
| 136 | +}; |
| 137 | + |
| 138 | +struct __fn : __range_adaptor_closure<__fn> { |
| 139 | + // [range.as.const.overview]: the basic `constant_range` case |
| 140 | + template <class _Range> |
| 141 | + requires constant_range<all_t<_Range>> |
| 142 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto |
| 143 | + operator()(_Range&& __range) noexcept(noexcept(views::all(std::forward<_Range>(__range)))) |
| 144 | + -> decltype(/*--------------------------*/ views::all(std::forward<_Range>(__range))) { |
| 145 | + return /*---------------------------------*/ views::all(std::forward<_Range>(__range)); |
| 146 | + } |
| 147 | + |
| 148 | + // [range.as.const.overview]: the `empty_view` case |
| 149 | + template <class _Range, class _UType = std::remove_cvref_t<_Range>> |
| 150 | + requires(!constant_range<all_t<_Range>>) && __has_type<__empty_view_case<_UType>> |
| 151 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto |
| 152 | + operator()(_Range&&) noexcept(noexcept(auto(views::empty<typename __empty_view_case<_UType>::type>))) |
| 153 | + -> decltype(/*------------------*/ auto(views::empty<typename __empty_view_case<_UType>::type>)) { |
| 154 | + return /*-------------------------*/ auto(views::empty<typename __empty_view_case<_UType>::type>); |
| 155 | + } |
| 156 | + |
| 157 | + // [range.as.const.overview]: the `span` case |
| 158 | + template <class _Range, class _UType = std::remove_cvref_t<_Range>> |
| 159 | + requires(!constant_range<all_t<_Range>>) && __has_type<__span_case<_UType>> |
| 160 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto |
| 161 | + operator()(_Range&& __range) noexcept(noexcept(typename __span_case<_UType>::type(std::forward<_UType>(__range)))) |
| 162 | + -> decltype(/*--------------------------*/ typename __span_case<_UType>::type(std::forward<_UType>(__range))) { |
| 163 | + return /*---------------------------------*/ typename __span_case<_UType>::type(std::forward<_UType>(__range)); |
| 164 | + } |
| 165 | + |
| 166 | + // [range.as.const.overview]: the `ref_view` case |
| 167 | + template <class _Range, class _UType = std::remove_cvref_t<_Range>> |
| 168 | + requires(!constant_range<all_t<_Range>>) && __has_type<__ref_view_case<_UType>> |
| 169 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept( |
| 170 | + noexcept(ref_view(static_cast<typename __ref_view_case<_UType>::type>(__range.base())))) |
| 171 | + -> decltype(/*--------------------------*/ ref_view( |
| 172 | + static_cast<typename __ref_view_case<_UType>::type>(__range.base()))) { |
| 173 | + return /*---------------------------------*/ ref_view( |
| 174 | + static_cast<typename __ref_view_case<_UType>::type>(__range.base())); |
| 175 | + } |
| 176 | + |
| 177 | + // [range.as.const.overview]: the second `constant_range` case |
| 178 | + template <class _Range, class _UType = std::remove_cvref_t<_Range>> |
| 179 | + requires(!constant_range<all_t<_Range>>) && is_lvalue_reference_v<_Range> && |
| 180 | + __has_type<__constant_range_case<_UType>> |
| 181 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept( |
| 182 | + noexcept(ref_view(static_cast<typename __constant_range_case<_UType>::type>(__range)))) |
| 183 | + -> decltype(/*--------------------------*/ ref_view( |
| 184 | + static_cast<typename __constant_range_case<_UType>::type>(__range))) { |
| 185 | + return /*---------------------------------*/ ref_view( |
| 186 | + static_cast<typename __constant_range_case<_UType>::type>(__range)); |
| 187 | + } |
| 188 | + |
| 189 | + // [range.as.const.overview]: otherwise |
| 190 | + template <class _Range> |
| 191 | + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto |
| 192 | + operator()(_Range&& __range) noexcept(noexcept(as_const_view(std::forward<_Range>(__range)))) |
| 193 | + -> decltype(/*--------------------------*/ as_const_view(std::forward<_Range>(__range))) { |
| 194 | + return /*---------------------------------*/ as_const_view(std::forward<_Range>(__range)); |
| 195 | + } |
| 196 | +}; |
| 197 | + |
| 198 | +} // namespace __as_const |
| 199 | + |
| 200 | +inline namespace __cpo { |
| 201 | +inline constexpr auto as_const = __as_const::__fn{}; |
| 202 | +} // namespace __cpo |
| 203 | +} // namespace views |
| 204 | + |
| 205 | +} // namespace ranges |
| 206 | + |
| 207 | +#endif // _LIBCPP_STD_VER >= 23 |
| 208 | + |
| 209 | +_LIBCPP_END_NAMESPACE_STD |
| 210 | + |
| 211 | +_LIBCPP_POP_MACROS |
| 212 | + |
| 213 | +#endif // _LIBCPP___RANGES_AS_CONST_VIEW_H |
0 commit comments