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 #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H
10 #define _LIBCPP___RANGES_VIEW_INTERFACE_H
11 
12 #include <__assert>
13 #include <__concepts/derived_from.h>
14 #include <__concepts/same_as.h>
15 #include <__config>
16 #include <__iterator/concepts.h>
17 #include <__iterator/iterator_traits.h>
18 #include <__iterator/prev.h>
19 #include <__memory/pointer_traits.h>
20 #include <__ranges/access.h>
21 #include <__ranges/concepts.h>
22 #include <__ranges/empty.h>
23 #include <type_traits>
24 
25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26 #  pragma GCC system_header
27 #endif
28 
29 _LIBCPP_BEGIN_NAMESPACE_STD
30 
31 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
32 
33 namespace ranges {
34 
35 template<class _Derived>
36   requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
37 class view_interface {
38   _LIBCPP_HIDE_FROM_ABI
39   constexpr _Derived& __derived() noexcept {
40     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
41     return static_cast<_Derived&>(*this);
42   }
43 
44   _LIBCPP_HIDE_FROM_ABI
45   constexpr _Derived const& __derived() const noexcept {
46     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
47     return static_cast<_Derived const&>(*this);
48   }
49 
50 public:
51   template<class _D2 = _Derived>
52   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
53     requires forward_range<_D2>
54   {
55     return ranges::begin(__derived()) == ranges::end(__derived());
56   }
57 
58   template<class _D2 = _Derived>
59   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
60     requires forward_range<const _D2>
61   {
62     return ranges::begin(__derived()) == ranges::end(__derived());
63   }
64 
65   template<class _D2 = _Derived>
66   _LIBCPP_HIDE_FROM_ABI
67   constexpr explicit operator bool()
68     requires requires (_D2& __t) { ranges::empty(__t); }
69   {
70     return !ranges::empty(__derived());
71   }
72 
73   template<class _D2 = _Derived>
74   _LIBCPP_HIDE_FROM_ABI
75   constexpr explicit operator bool() const
76     requires requires (const _D2& __t) { ranges::empty(__t); }
77   {
78     return !ranges::empty(__derived());
79   }
80 
81   template<class _D2 = _Derived>
82   _LIBCPP_HIDE_FROM_ABI
83   constexpr auto data()
84     requires contiguous_iterator<iterator_t<_D2>>
85   {
86     return std::to_address(ranges::begin(__derived()));
87   }
88 
89   template<class _D2 = _Derived>
90   _LIBCPP_HIDE_FROM_ABI
91   constexpr auto data() const
92     requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
93   {
94     return std::to_address(ranges::begin(__derived()));
95   }
96 
97   template<class _D2 = _Derived>
98   _LIBCPP_HIDE_FROM_ABI
99   constexpr auto size()
100     requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
101   {
102     return ranges::end(__derived()) - ranges::begin(__derived());
103   }
104 
105   template<class _D2 = _Derived>
106   _LIBCPP_HIDE_FROM_ABI
107   constexpr auto size() const
108     requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
109   {
110     return ranges::end(__derived()) - ranges::begin(__derived());
111   }
112 
113   template<class _D2 = _Derived>
114   _LIBCPP_HIDE_FROM_ABI
115   constexpr decltype(auto) front()
116     requires forward_range<_D2>
117   {
118     _LIBCPP_ASSERT(!empty(),
119         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
120     return *ranges::begin(__derived());
121   }
122 
123   template<class _D2 = _Derived>
124   _LIBCPP_HIDE_FROM_ABI
125   constexpr decltype(auto) front() const
126     requires forward_range<const _D2>
127   {
128     _LIBCPP_ASSERT(!empty(),
129         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
130     return *ranges::begin(__derived());
131   }
132 
133   template<class _D2 = _Derived>
134   _LIBCPP_HIDE_FROM_ABI
135   constexpr decltype(auto) back()
136     requires bidirectional_range<_D2> && common_range<_D2>
137   {
138     _LIBCPP_ASSERT(!empty(),
139         "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
140     return *ranges::prev(ranges::end(__derived()));
141   }
142 
143   template<class _D2 = _Derived>
144   _LIBCPP_HIDE_FROM_ABI
145   constexpr decltype(auto) back() const
146     requires bidirectional_range<const _D2> && common_range<const _D2>
147   {
148     _LIBCPP_ASSERT(!empty(),
149         "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
150     return *ranges::prev(ranges::end(__derived()));
151   }
152 
153   template<random_access_range _RARange = _Derived>
154   _LIBCPP_HIDE_FROM_ABI
155   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index)
156   {
157     return ranges::begin(__derived())[__index];
158   }
159 
160   template<random_access_range _RARange = const _Derived>
161   _LIBCPP_HIDE_FROM_ABI
162   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const
163   {
164     return ranges::begin(__derived())[__index];
165   }
166 };
167 
168 } // namespace ranges
169 
170 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
171 
172 _LIBCPP_END_NAMESPACE_STD
173 
174 #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H
175