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 #include <type_traits>
28 
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 #  pragma GCC system_header
31 #endif
32 
33 _LIBCPP_BEGIN_NAMESPACE_STD
34 
35 #if _LIBCPP_STD_VER > 17
36 
37 namespace ranges {
38 
39 template<view _View>
40   requires (!common_range<_View> && copyable<iterator_t<_View>>)
41 class common_view : public view_interface<common_view<_View>> {
42   _View __base_ = _View();
43 
44 public:
45   _LIBCPP_HIDE_FROM_ABI
46   common_view() requires default_initializable<_View> = default;
47 
48   _LIBCPP_HIDE_FROM_ABI
49   constexpr explicit common_view(_View __v) : __base_(std::move(__v)) { }
50 
51   _LIBCPP_HIDE_FROM_ABI
52   constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
53 
54   _LIBCPP_HIDE_FROM_ABI
55   constexpr _View base() && { return std::move(__base_); }
56 
57   _LIBCPP_HIDE_FROM_ABI
58   constexpr auto begin() {
59     if constexpr (random_access_range<_View> && sized_range<_View>)
60       return ranges::begin(__base_);
61     else
62       return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::begin(__base_));
63   }
64 
65   _LIBCPP_HIDE_FROM_ABI
66   constexpr auto begin() const requires range<const _View> {
67     if constexpr (random_access_range<const _View> && sized_range<const _View>)
68       return ranges::begin(__base_);
69     else
70       return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
71   }
72 
73   _LIBCPP_HIDE_FROM_ABI
74   constexpr auto end() {
75     if constexpr (random_access_range<_View> && sized_range<_View>)
76       return ranges::begin(__base_) + ranges::size(__base_);
77     else
78       return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::end(__base_));
79   }
80 
81   _LIBCPP_HIDE_FROM_ABI
82   constexpr auto end() const requires range<const _View> {
83     if constexpr (random_access_range<const _View> && sized_range<const _View>)
84       return ranges::begin(__base_) + ranges::size(__base_);
85     else
86       return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::end(__base_));
87   }
88 
89   _LIBCPP_HIDE_FROM_ABI
90   constexpr auto size() requires sized_range<_View> {
91     return ranges::size(__base_);
92   }
93 
94   _LIBCPP_HIDE_FROM_ABI
95   constexpr auto size() const requires sized_range<const _View> {
96     return ranges::size(__base_);
97   }
98 };
99 
100 template<class _Range>
101 common_view(_Range&&)
102   -> common_view<views::all_t<_Range>>;
103 
104 template<class _View>
105 inline constexpr bool enable_borrowed_range<common_view<_View>> = enable_borrowed_range<_View>;
106 
107 namespace views {
108 namespace __common {
109   struct __fn : __range_adaptor_closure<__fn> {
110     template<class _Range>
111       requires common_range<_Range>
112     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
113     constexpr auto operator()(_Range&& __range) const
114       noexcept(noexcept(views::all(std::forward<_Range>(__range))))
115       -> decltype(      views::all(std::forward<_Range>(__range)))
116       { return          views::all(std::forward<_Range>(__range)); }
117 
118     template<class _Range>
119     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
120     constexpr auto operator()(_Range&& __range) const
121       noexcept(noexcept(common_view{std::forward<_Range>(__range)}))
122       -> decltype(      common_view{std::forward<_Range>(__range)})
123       { return          common_view{std::forward<_Range>(__range)}; }
124   };
125 } // namespace __common
126 
127 inline namespace __cpo {
128   inline constexpr auto common = __common::__fn{};
129 } // namespace __cpo
130 } // namespace views
131 } // namespace ranges
132 
133 #endif // _LIBCPP_STD_VER > 17
134 
135 _LIBCPP_END_NAMESPACE_STD
136 
137 #endif // _LIBCPP___RANGES_COMMON_VIEW_H
138