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_ELEMENTS_VIEW_H 11 #define _LIBCPP___RANGES_ELEMENTS_VIEW_H 12 13 #include <__compare/three_way_comparable.h> 14 #include <__concepts/constructible.h> 15 #include <__concepts/convertible_to.h> 16 #include <__concepts/derived_from.h> 17 #include <__concepts/equality_comparable.h> 18 #include <__config> 19 #include <__fwd/get.h> 20 #include <__iterator/concepts.h> 21 #include <__iterator/iterator_traits.h> 22 #include <__ranges/access.h> 23 #include <__ranges/all.h> 24 #include <__ranges/concepts.h> 25 #include <__ranges/enable_borrowed_range.h> 26 #include <__ranges/range_adaptor.h> 27 #include <__ranges/size.h> 28 #include <__ranges/view_interface.h> 29 #include <__tuple/tuple_element.h> 30 #include <__tuple/tuple_like.h> 31 #include <__tuple/tuple_size.h> 32 #include <__type_traits/is_reference.h> 33 #include <__type_traits/maybe_const.h> 34 #include <__type_traits/remove_cv.h> 35 #include <__type_traits/remove_cvref.h> 36 #include <__type_traits/remove_reference.h> 37 #include <__utility/declval.h> 38 #include <__utility/forward.h> 39 #include <__utility/move.h> 40 #include <cstddef> 41 42 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 43 # pragma GCC system_header 44 #endif 45 46 _LIBCPP_BEGIN_NAMESPACE_STD 47 48 #if _LIBCPP_STD_VER >= 20 49 50 namespace ranges { 51 52 template <class _Tp, size_t _Np> 53 concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; 54 55 template <class _Tp, size_t _Np> 56 concept __returnable_element = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Np, _Tp>>; 57 58 template <input_range _View, size_t _Np> 59 requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && 60 __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && 61 __returnable_element<range_reference_t<_View>, _Np> 62 class elements_view : public view_interface<elements_view<_View, _Np>> { 63 private: 64 template <bool> 65 class __iterator; 66 67 template <bool> 68 class __sentinel; 69 70 public: 71 _LIBCPP_HIDE_FROM_ABI elements_view() 72 requires default_initializable<_View> 73 = default; 74 75 _LIBCPP_HIDE_FROM_ABI constexpr explicit elements_view(_View __base) : __base_(std::move(__base)) {} 76 77 _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 78 requires copy_constructible<_View> 79 { 80 return __base_; 81 } 82 83 _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 84 85 _LIBCPP_HIDE_FROM_ABI constexpr auto begin() 86 requires(!__simple_view<_View>) 87 { 88 return __iterator</*_Const=*/false>(ranges::begin(__base_)); 89 } 90 91 _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const 92 requires range<const _View> 93 { 94 return __iterator</*_Const=*/true>(ranges::begin(__base_)); 95 } 96 97 _LIBCPP_HIDE_FROM_ABI constexpr auto end() 98 requires(!__simple_view<_View> && !common_range<_View>) 99 { 100 return __sentinel</*_Const=*/false>{ranges::end(__base_)}; 101 } 102 103 _LIBCPP_HIDE_FROM_ABI constexpr auto end() 104 requires(!__simple_view<_View> && common_range<_View>) 105 { 106 return __iterator</*_Const=*/false>{ranges::end(__base_)}; 107 } 108 109 _LIBCPP_HIDE_FROM_ABI constexpr auto end() const 110 requires range<const _View> 111 { 112 return __sentinel</*_Const=*/true>{ranges::end(__base_)}; 113 } 114 115 _LIBCPP_HIDE_FROM_ABI constexpr auto end() const 116 requires common_range<const _View> 117 { 118 return __iterator</*_Const=*/true>{ranges::end(__base_)}; 119 } 120 121 _LIBCPP_HIDE_FROM_ABI constexpr auto size() 122 requires sized_range<_View> 123 { 124 return ranges::size(__base_); 125 } 126 127 _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 128 requires sized_range<const _View> 129 { 130 return ranges::size(__base_); 131 } 132 133 private: 134 _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 135 }; 136 137 template <class, size_t> 138 struct __elements_view_iterator_category_base {}; 139 140 template <forward_range _Base, size_t _Np> 141 struct __elements_view_iterator_category_base<_Base, _Np> { 142 static consteval auto __get_iterator_category() { 143 using _Result = decltype(std::get<_Np>(*std::declval<iterator_t<_Base>>())); 144 using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; 145 146 if constexpr (!is_lvalue_reference_v<_Result>) { 147 return input_iterator_tag{}; 148 } else if constexpr (derived_from<_Cat, random_access_iterator_tag>) { 149 return random_access_iterator_tag{}; 150 } else { 151 return _Cat{}; 152 } 153 } 154 155 using iterator_category = decltype(__get_iterator_category()); 156 }; 157 158 template <input_range _View, size_t _Np> 159 requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && 160 __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && 161 __returnable_element<range_reference_t<_View>, _Np> 162 template <bool _Const> 163 class elements_view<_View, _Np>::__iterator 164 : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { 165 template <bool> 166 friend class __iterator; 167 168 template <bool> 169 friend class __sentinel; 170 171 using _Base = __maybe_const<_Const, _View>; 172 173 iterator_t<_Base> __current_ = iterator_t<_Base>(); 174 175 _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) { 176 if constexpr (is_reference_v<range_reference_t<_Base>>) { 177 return std::get<_Np>(*__i); 178 } else { 179 using _Element = remove_cv_t<tuple_element_t<_Np, range_reference_t<_Base>>>; 180 return static_cast<_Element>(std::get<_Np>(*__i)); 181 } 182 } 183 184 static consteval auto __get_iterator_concept() { 185 if constexpr (random_access_range<_Base>) { 186 return random_access_iterator_tag{}; 187 } else if constexpr (bidirectional_range<_Base>) { 188 return bidirectional_iterator_tag{}; 189 } else if constexpr (forward_range<_Base>) { 190 return forward_iterator_tag{}; 191 } else { 192 return input_iterator_tag{}; 193 } 194 } 195 196 public: 197 using iterator_concept = decltype(__get_iterator_concept()); 198 using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; 199 using difference_type = range_difference_t<_Base>; 200 201 _LIBCPP_HIDE_FROM_ABI __iterator() 202 requires default_initializable<iterator_t<_Base>> 203 = default; 204 205 _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {} 206 207 _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) 208 requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> 209 : __current_(std::move(__i.__current_)) {} 210 211 _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; } 212 213 _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); } 214 215 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); } 216 217 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 218 ++__current_; 219 return *this; 220 } 221 222 _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } 223 224 _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) 225 requires forward_range<_Base> 226 { 227 auto __temp = *this; 228 ++__current_; 229 return __temp; 230 } 231 232 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() 233 requires bidirectional_range<_Base> 234 { 235 --__current_; 236 return *this; 237 } 238 239 _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) 240 requires bidirectional_range<_Base> 241 { 242 auto __temp = *this; 243 --__current_; 244 return __temp; 245 } 246 247 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) 248 requires random_access_range<_Base> 249 { 250 __current_ += __n; 251 return *this; 252 } 253 254 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) 255 requires random_access_range<_Base> 256 { 257 __current_ -= __n; 258 return *this; 259 } 260 261 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const 262 requires random_access_range<_Base> 263 { 264 return __get_element(__current_ + __n); 265 } 266 267 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) 268 requires equality_comparable<iterator_t<_Base>> 269 { 270 return __x.__current_ == __y.__current_; 271 } 272 273 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) 274 requires random_access_range<_Base> 275 { 276 return __x.__current_ < __y.__current_; 277 } 278 279 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) 280 requires random_access_range<_Base> 281 { 282 return __y < __x; 283 } 284 285 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) 286 requires random_access_range<_Base> 287 { 288 return !(__y < __x); 289 } 290 291 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) 292 requires random_access_range<_Base> 293 { 294 return !(__x < __y); 295 } 296 297 _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) 298 requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> 299 { 300 return __x.__current_ <=> __y.__current_; 301 } 302 303 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y) 304 requires random_access_range<_Base> 305 { 306 return __iterator{__x} += __y; 307 } 308 309 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y) 310 requires random_access_range<_Base> 311 { 312 return __y + __x; 313 } 314 315 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y) 316 requires random_access_range<_Base> 317 { 318 return __iterator{__x} -= __y; 319 } 320 321 _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) 322 requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> 323 { 324 return __x.__current_ - __y.__current_; 325 } 326 }; 327 328 template <input_range _View, size_t _Np> 329 requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && 330 __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && 331 __returnable_element<range_reference_t<_View>, _Np> 332 template <bool _Const> 333 class elements_view<_View, _Np>::__sentinel { 334 private: 335 using _Base = __maybe_const<_Const, _View>; 336 _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); 337 338 template <bool> 339 friend class __sentinel; 340 341 template <bool _AnyConst> 342 _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) { 343 return (__iter.__current_); 344 } 345 346 public: 347 _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 348 349 _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} 350 351 _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other) 352 requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> 353 : __end_(std::move(__other.__end_)) {} 354 355 _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } 356 357 template <bool _OtherConst> 358 requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 359 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { 360 return __get_current(__x) == __y.__end_; 361 } 362 363 template <bool _OtherConst> 364 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 365 _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> 366 operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { 367 return __get_current(__x) - __y.__end_; 368 } 369 370 template <bool _OtherConst> 371 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 372 _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> 373 operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { 374 return __x.__end_ - __get_current(__y); 375 } 376 }; 377 378 template <class _Tp, size_t _Np> 379 inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Np>> = enable_borrowed_range<_Tp>; 380 381 template <class _Tp> 382 using keys_view = elements_view<_Tp, 0>; 383 template <class _Tp> 384 using values_view = elements_view<_Tp, 1>; 385 386 namespace views { 387 namespace __elements { 388 389 template <size_t _Np> 390 struct __fn : __range_adaptor_closure<__fn<_Np>> { 391 template <class _Range> 392 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const 393 /**/ noexcept(noexcept(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)))) 394 /*------*/ -> decltype(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))) { 395 /*-------------*/ return elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)); 396 } 397 }; 398 } // namespace __elements 399 400 inline namespace __cpo { 401 template <size_t _Np> 402 inline constexpr auto elements = __elements::__fn<_Np>{}; 403 inline constexpr auto keys = elements<0>; 404 inline constexpr auto values = elements<1>; 405 } // namespace __cpo 406 } // namespace views 407 } // namespace ranges 408 409 #endif // _LIBCPP_STD_VER >= 20 410 411 _LIBCPP_END_NAMESPACE_STD 412 413 #endif // _LIBCPP___RANGES_ELEMENTS_VIEW_H 414