2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H
11 #define _LIBCPP___RANGES_VIEW_INTERFACE_H
14 #include <__concepts/derived_from.h>
15 #include <__concepts/same_as.h>
17 #include <__iterator/concepts.h>
18 #include <__iterator/iterator_traits.h>
19 #include <__iterator/prev.h>
20 #include <__memory/pointer_traits.h>
21 #include <__ranges/access.h>
22 #include <__ranges/concepts.h>
23 #include <__ranges/empty.h>
24 #include <__ranges/size.h>
25 #include <__type_traits/is_class.h>
26 #include <__type_traits/make_unsigned.h>
27 #include <__type_traits/remove_cv.h>
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 # pragma GCC system_header
33 _LIBCPP_BEGIN_NAMESPACE_STD
35 #if _LIBCPP_STD_VER >= 20
39 template <class _Derived
>
40 requires is_class_v
<_Derived
> && same_as
<_Derived
, remove_cv_t
<_Derived
>>
41 class view_interface
{
42 _LIBCPP_HIDE_FROM_ABI
constexpr _Derived
& __derived() noexcept
{
43 static_assert(sizeof(_Derived
) && derived_from
<_Derived
, view_interface
> && view
<_Derived
>);
44 return static_cast<_Derived
&>(*this);
47 _LIBCPP_HIDE_FROM_ABI
constexpr _Derived
const& __derived() const noexcept
{
48 static_assert(sizeof(_Derived
) && derived_from
<_Derived
, view_interface
> && view
<_Derived
>);
49 return static_cast<_Derived
const&>(*this);
53 template <class _D2
= _Derived
>
54 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr bool empty()
55 requires sized_range
<_D2
> || forward_range
<_D2
>
57 if constexpr (sized_range
<_D2
>) {
58 return ranges::size(__derived()) == 0;
60 return ranges::begin(__derived()) == ranges::end(__derived());
64 template <class _D2
= _Derived
>
65 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr bool empty() const
66 requires sized_range
<const _D2
> || forward_range
<const _D2
>
68 if constexpr (sized_range
<const _D2
>) {
69 return ranges::size(__derived()) == 0;
71 return ranges::begin(__derived()) == ranges::end(__derived());
75 template <class _D2
= _Derived
>
76 _LIBCPP_HIDE_FROM_ABI
constexpr explicit operator bool()
77 requires
requires(_D2
& __t
) { ranges::empty(__t
); }
79 return !ranges::empty(__derived());
82 template <class _D2
= _Derived
>
83 _LIBCPP_HIDE_FROM_ABI
constexpr explicit operator bool() const
84 requires
requires(const _D2
& __t
) { ranges::empty(__t
); }
86 return !ranges::empty(__derived());
89 template <class _D2
= _Derived
>
90 _LIBCPP_HIDE_FROM_ABI
constexpr auto data()
91 requires contiguous_iterator
<iterator_t
<_D2
>>
93 return std::to_address(ranges::begin(__derived()));
96 template <class _D2
= _Derived
>
97 _LIBCPP_HIDE_FROM_ABI
constexpr auto data() const
98 requires range
<const _D2
> && contiguous_iterator
<iterator_t
<const _D2
>>
100 return std::to_address(ranges::begin(__derived()));
103 template <class _D2
= _Derived
>
104 _LIBCPP_HIDE_FROM_ABI
constexpr auto size()
105 requires forward_range
<_D2
> && sized_sentinel_for
<sentinel_t
<_D2
>, iterator_t
<_D2
>>
107 return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
110 template <class _D2
= _Derived
>
111 _LIBCPP_HIDE_FROM_ABI
constexpr auto size() const
112 requires forward_range
<const _D2
> && sized_sentinel_for
<sentinel_t
<const _D2
>, iterator_t
<const _D2
>>
114 return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
117 template <class _D2
= _Derived
>
118 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) front()
119 requires forward_range
<_D2
>
121 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
122 !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
123 return *ranges::begin(__derived());
126 template <class _D2
= _Derived
>
127 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) front() const
128 requires forward_range
<const _D2
>
130 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
131 !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
132 return *ranges::begin(__derived());
135 template <class _D2
= _Derived
>
136 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) back()
137 requires bidirectional_range
<_D2
> && common_range
<_D2
>
139 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
140 !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
141 return *ranges::prev(ranges::end(__derived()));
144 template <class _D2
= _Derived
>
145 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) back() const
146 requires bidirectional_range
<const _D2
> && common_range
<const _D2
>
148 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
149 !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
150 return *ranges::prev(ranges::end(__derived()));
153 template <random_access_range _RARange
= _Derived
>
154 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) operator[](range_difference_t
<_RARange
> __index
) {
155 return ranges::begin(__derived())[__index
];
158 template <random_access_range _RARange
= const _Derived
>
159 _LIBCPP_HIDE_FROM_ABI
constexpr decltype(auto) operator[](range_difference_t
<_RARange
> __index
) const {
160 return ranges::begin(__derived())[__index
];
164 } // namespace ranges
166 #endif // _LIBCPP_STD_VER >= 20
168 _LIBCPP_END_NAMESPACE_STD
170 #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H