xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/concepts.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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_CONCEPTS_H
11 #define _LIBCPP___RANGES_CONCEPTS_H
12 
13 #include <__concepts/common_reference_with.h>
14 #include <__concepts/constructible.h>
15 #include <__concepts/convertible_to.h>
16 #include <__concepts/movable.h>
17 #include <__concepts/same_as.h>
18 #include <__config>
19 #include <__iterator/concepts.h>
20 #include <__iterator/incrementable_traits.h>
21 #include <__iterator/iter_move.h>
22 #include <__iterator/iterator_traits.h>
23 #include <__iterator/readable_traits.h>
24 #include <__ranges/access.h>
25 #include <__ranges/data.h>
26 #include <__ranges/enable_borrowed_range.h>
27 #include <__ranges/enable_view.h>
28 #include <__ranges/size.h>
29 #include <__type_traits/add_pointer.h>
30 #include <__type_traits/common_reference.h>
31 #include <__type_traits/common_type.h>
32 #include <__type_traits/is_reference.h>
33 #include <__type_traits/remove_cvref.h>
34 #include <__type_traits/remove_reference.h>
35 #include <__utility/declval.h>
36 #include <initializer_list>
37 
38 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
39 #  pragma GCC system_header
40 #endif
41 
42 _LIBCPP_BEGIN_NAMESPACE_STD
43 
44 #if _LIBCPP_STD_VER >= 20
45 
46 namespace ranges {
47 
48 // [range.range]
49 
50 template <class _Tp>
requires(_Tp & __t)51 concept range = requires(_Tp& __t) {
52   ranges::begin(__t); // sometimes equality-preserving
53   ranges::end(__t);
54 };
55 
56 template <class _Tp>
57 concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
58 
59 template <class _Range>
60 concept borrowed_range =
61     range<_Range> && (is_lvalue_reference_v<_Range> || enable_borrowed_range<remove_cvref_t<_Range>>);
62 
63 // `iterator_t` defined in <__ranges/access.h>
64 
65 template <range _Rp>
66 using sentinel_t = decltype(ranges::end(std::declval<_Rp&>()));
67 
68 template <range _Rp>
69 using range_difference_t = iter_difference_t<iterator_t<_Rp>>;
70 
71 template <range _Rp>
72 using range_value_t = iter_value_t<iterator_t<_Rp>>;
73 
74 template <range _Rp>
75 using range_reference_t = iter_reference_t<iterator_t<_Rp>>;
76 
77 template <range _Rp>
78 using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
79 
80 template <range _Rp>
81 using range_common_reference_t = iter_common_reference_t<iterator_t<_Rp>>;
82 
83 // [range.sized]
84 template <class _Tp>
requires(_Tp & __t)85 concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
86 
87 template <sized_range _Rp>
88 using range_size_t = decltype(ranges::size(std::declval<_Rp&>()));
89 
90 // `disable_sized_range` defined in `<__ranges/size.h>`
91 
92 // [range.view], views
93 
94 // `enable_view` defined in <__ranges/enable_view.h>
95 // `view_base` defined in <__ranges/enable_view.h>
96 
97 template <class _Tp>
98 concept view = range<_Tp> && movable<_Tp> && enable_view<_Tp>;
99 
100 template <class _Range>
101 concept __simple_view =
102     view<_Range> && range<const _Range> && same_as<iterator_t<_Range>, iterator_t<const _Range>> &&
103     same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
104 
105 // [range.refinements], other range refinements
106 template <class _Rp, class _Tp>
107 concept output_range = range<_Rp> && output_iterator<iterator_t<_Rp>, _Tp>;
108 
109 template <class _Tp>
110 concept forward_range = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
111 
112 template <class _Tp>
113 concept bidirectional_range = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
114 
115 template <class _Tp>
116 concept random_access_range = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
117 
118 template <class _Tp>
requires(_Tp & __t)119 concept contiguous_range = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>> && requires(_Tp& __t) {
120   { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
121 };
122 
123 template <class _Tp>
124 concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
125 
126 template <class _Tp>
127 inline constexpr bool __is_std_initializer_list = false;
128 
129 template <class _Ep>
130 inline constexpr bool __is_std_initializer_list<initializer_list<_Ep>> = true;
131 
132 template <class _Tp>
133 concept viewable_range =
134     range<_Tp> &&
135     ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) ||
136      (!view<remove_cvref_t<_Tp>> &&
137       (is_lvalue_reference_v<_Tp> ||
138        (movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>))));
139 
140 #  if _LIBCPP_STD_VER >= 23
141 
142 template <class... _Rs>
143 using __concat_reference_t _LIBCPP_NODEBUG = common_reference_t<range_reference_t<_Rs>...>;
144 
145 template <class... _Rs>
146 using __concat_value_t _LIBCPP_NODEBUG = common_type_t<range_value_t<_Rs>...>;
147 
148 template <class... _Rs>
149 using __concat_rvalue_reference_t _LIBCPP_NODEBUG = common_reference_t<range_rvalue_reference_t<_Rs>...>;
150 
151 template <class _Ref, class _RRef, class _It>
requires(const _It __it)152 concept __concat_indirectly_readable_impl = requires(const _It __it) {
153   { *__it } -> convertible_to<_Ref>;
154   { ranges::iter_move(__it) } -> convertible_to<_RRef>;
155 };
156 
157 template <class... _Rs>
158 concept __concat_indirectly_readable =
159     common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&> &&
160     common_reference_with<__concat_reference_t<_Rs...>&&, __concat_rvalue_reference_t<_Rs...>&&> &&
161     common_reference_with<__concat_rvalue_reference_t<_Rs...>&&, const __concat_value_t<_Rs...>&> &&
162     (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
163                                        __concat_rvalue_reference_t<_Rs...>,
164                                        iterator_t<_Rs>> &&
165      ...);
166 
167 template <class... _Rs>
168 concept __concatable = requires {
169   typename __concat_reference_t<_Rs...>;
170   typename __concat_value_t<_Rs...>;
171   typename __concat_rvalue_reference_t<_Rs...>;
172 } && __concat_indirectly_readable<_Rs...>;
173 
174 #  endif // _LIBCPP_STD_VER >= 23
175 
176 } // namespace ranges
177 
178 #endif // _LIBCPP_STD_VER >= 20
179 
180 _LIBCPP_END_NAMESPACE_STD
181 
182 #endif // _LIBCPP___RANGES_CONCEPTS_H
183