Path: blob/main/contrib/llvm-project/libcxx/include/__ranges/reverse_view.h
35236 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___RANGES_REVERSE_VIEW_H10#define _LIBCPP___RANGES_REVERSE_VIEW_H1112#include <__concepts/constructible.h>13#include <__config>14#include <__iterator/concepts.h>15#include <__iterator/next.h>16#include <__iterator/reverse_iterator.h>17#include <__ranges/access.h>18#include <__ranges/all.h>19#include <__ranges/concepts.h>20#include <__ranges/enable_borrowed_range.h>21#include <__ranges/non_propagating_cache.h>22#include <__ranges/range_adaptor.h>23#include <__ranges/size.h>24#include <__ranges/subrange.h>25#include <__ranges/view_interface.h>26#include <__type_traits/conditional.h>27#include <__type_traits/remove_cvref.h>28#include <__utility/forward.h>29#include <__utility/move.h>3031#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)32# pragma GCC system_header33#endif3435_LIBCPP_PUSH_MACROS36#include <__undef_macros>3738_LIBCPP_BEGIN_NAMESPACE_STD3940#if _LIBCPP_STD_VER >= 204142namespace ranges {43template <view _View>44requires bidirectional_range<_View>45class reverse_view : public view_interface<reverse_view<_View>> {46// We cache begin() whenever ranges::next is not guaranteed O(1) to provide an47// amortized O(1) begin() method.48static constexpr bool _UseCache = !random_access_range<_View> && !common_range<_View>;49using _Cache = _If<_UseCache, __non_propagating_cache<reverse_iterator<iterator_t<_View>>>, __empty_cache>;50_LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();51_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();5253public:54_LIBCPP_HIDE_FROM_ABI reverse_view()55requires default_initializable<_View>56= default;5758_LIBCPP_HIDE_FROM_ABI constexpr explicit reverse_view(_View __view) : __base_(std::move(__view)) {}5960_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&61requires copy_constructible<_View>62{63return __base_;64}6566_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }6768_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin() {69if constexpr (_UseCache)70if (__cached_begin_.__has_value())71return *__cached_begin_;7273auto __tmp = std::make_reverse_iterator(ranges::next(ranges::begin(__base_), ranges::end(__base_)));74if constexpr (_UseCache)75__cached_begin_.__emplace(__tmp);76return __tmp;77}7879_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin()80requires common_range<_View>81{82return std::make_reverse_iterator(ranges::end(__base_));83}8485_LIBCPP_HIDE_FROM_ABI constexpr auto begin() const86requires common_range<const _View>87{88return std::make_reverse_iterator(ranges::end(__base_));89}9091_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> end() {92return std::make_reverse_iterator(ranges::begin(__base_));93}9495_LIBCPP_HIDE_FROM_ABI constexpr auto end() const96requires common_range<const _View>97{98return std::make_reverse_iterator(ranges::begin(__base_));99}100101_LIBCPP_HIDE_FROM_ABI constexpr auto size()102requires sized_range<_View>103{104return ranges::size(__base_);105}106107_LIBCPP_HIDE_FROM_ABI constexpr auto size() const108requires sized_range<const _View>109{110return ranges::size(__base_);111}112};113114template <class _Range>115reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>;116117template <class _Tp>118inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> = enable_borrowed_range<_Tp>;119120namespace views {121namespace __reverse {122template <class _Tp>123inline constexpr bool __is_reverse_view = false;124125template <class _Tp>126inline constexpr bool __is_reverse_view<reverse_view<_Tp>> = true;127128template <class _Tp>129inline constexpr bool __is_sized_reverse_subrange = false;130131template <class _Iter>132inline constexpr bool133__is_sized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, subrange_kind::sized>> =134true;135136template <class _Tp>137inline constexpr bool __is_unsized_reverse_subrange = false;138139template <class _Iter, subrange_kind _Kind>140inline constexpr bool __is_unsized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> =141_Kind == subrange_kind::unsized;142143template <class _Tp>144struct __unwrapped_reverse_subrange {145using type =146void; // avoid SFINAE-ing out the overload below -- let the concept requirements do it for better diagnostics147};148149template <class _Iter, subrange_kind _Kind>150struct __unwrapped_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> {151using type = subrange<_Iter, _Iter, _Kind>;152};153154struct __fn : __range_adaptor_closure<__fn> {155template <class _Range>156requires __is_reverse_view<remove_cvref_t<_Range>>157[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const158noexcept(noexcept(std::forward<_Range>(__range).base())) -> decltype(std::forward<_Range>(__range).base()) {159return std::forward<_Range>(__range).base();160}161162template <class _Range,163class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>164requires __is_sized_reverse_subrange<remove_cvref_t<_Range>>165[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const166noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())))167-> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())) {168return _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size());169}170171template <class _Range,172class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>173requires __is_unsized_reverse_subrange<remove_cvref_t<_Range>>174[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const175noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base())))176-> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base())) {177return _UnwrappedSubrange(__range.end().base(), __range.begin().base());178}179180template <class _Range>181requires(!__is_reverse_view<remove_cvref_t<_Range>> && !__is_sized_reverse_subrange<remove_cvref_t<_Range>> &&182!__is_unsized_reverse_subrange<remove_cvref_t<_Range>>)183[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const noexcept(noexcept(reverse_view{184std::forward<_Range>(__range)})) -> decltype(reverse_view{std::forward<_Range>(__range)}) {185return reverse_view{std::forward<_Range>(__range)};186}187};188} // namespace __reverse189190inline namespace __cpo {191inline constexpr auto reverse = __reverse::__fn{};192} // namespace __cpo193} // namespace views194} // namespace ranges195196#endif // _LIBCPP_STD_VER >= 20197198_LIBCPP_END_NAMESPACE_STD199200_LIBCPP_POP_MACROS201202#endif // _LIBCPP___RANGES_REVERSE_VIEW_H203204205