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_COMMON_VIEW_H
11 #define _LIBCPP___RANGES_COMMON_VIEW_H
12 
13 #include <__concepts/constructible.h>
14 #include <__concepts/copyable.h>
15 #include <__config>
16 #include <__iterator/common_iterator.h>
17 #include <__iterator/iterator_traits.h>
18 #include <__ranges/access.h>
19 #include <__ranges/all.h>
20 #include <__ranges/concepts.h>
21 #include <__ranges/enable_borrowed_range.h>
22 #include <__ranges/range_adaptor.h>
23 #include <__ranges/size.h>
24 #include <__ranges/view_interface.h>
25 #include <__utility/forward.h>
26 #include <__utility/move.h>
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 >= 20
38 
39 namespace ranges {
40 
41 template <view _View>
42   requires(!common_range<_View> && copyable<iterator_t<_View>>)
43 class common_view : public view_interface<common_view<_View>> {
44   _View __base_ = _View();
45 
46 public:
47   _LIBCPP_HIDE_FROM_ABI common_view()
48     requires default_initializable<_View>
49   = default;
50 
common_view(_View __v)51   _LIBCPP_HIDE_FROM_ABI constexpr explicit common_view(_View __v) : __base_(std::move(__v)) {}
52 
base()53   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
54     requires copy_constructible<_View>
55   {
56     return __base_;
57   }
58 
base()59   _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
60 
begin()61   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
62     if constexpr (random_access_range<_View> && sized_range<_View>)
63       return ranges::begin(__base_);
64     else
65       return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::begin(__base_));
66   }
67 
begin()68   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
69     requires range<const _View>
70   {
71     if constexpr (random_access_range<const _View> && sized_range<const _View>)
72       return ranges::begin(__base_);
73     else
74       return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
75   }
76 
end()77   _LIBCPP_HIDE_FROM_ABI constexpr auto end() {
78     if constexpr (random_access_range<_View> && sized_range<_View>)
79       return ranges::begin(__base_) + ranges::size(__base_);
80     else
81       return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::end(__base_));
82   }
83 
end()84   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
85     requires range<const _View>
86   {
87     if constexpr (random_access_range<const _View> && sized_range<const _View>)
88       return ranges::begin(__base_) + ranges::size(__base_);
89     else
90       return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::end(__base_));
91   }
92 
size()93   _LIBCPP_HIDE_FROM_ABI constexpr auto size()
94     requires sized_range<_View>
95   {
96     return ranges::size(__base_);
97   }
98 
size()99   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
100     requires sized_range<const _View>
101   {
102     return ranges::size(__base_);
103   }
104 };
105 
106 template <class _Range>
107 common_view(_Range&&) -> common_view<views::all_t<_Range>>;
108 
109 template <class _View>
110 inline constexpr bool enable_borrowed_range<common_view<_View>> = enable_borrowed_range<_View>;
111 
112 namespace views {
113 namespace __common {
114 struct __fn : __range_adaptor_closure<__fn> {
115   template <class _Range>
116     requires common_range<_Range>
117   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
118       noexcept(noexcept(views::all(std::forward<_Range>(__range))))
119           -> decltype(views::all(std::forward<_Range>(__range))) {
120     return views::all(std::forward<_Range>(__range));
121   }
122 
123   template <class _Range>
124   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
125       noexcept(noexcept(common_view{std::forward<_Range>(__range)}))
126           -> decltype(common_view{std::forward<_Range>(__range)}) {
127     return common_view{std::forward<_Range>(__range)};
128   }
129 };
130 } // namespace __common
131 
132 inline namespace __cpo {
133 inline constexpr auto common = __common::__fn{};
134 } // namespace __cpo
135 } // namespace views
136 } // namespace ranges
137 
138 #endif // _LIBCPP_STD_VER >= 20
139 
140 _LIBCPP_END_NAMESPACE_STD
141 
142 _LIBCPP_POP_MACROS
143 
144 #endif // _LIBCPP___RANGES_COMMON_VIEW_H
145