Horizon
Loading...
Searching...
No Matches
primitives.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2014-present
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12//
13
14#ifndef RANGES_V3_RANGE_PRIMITIVES_HPP
15#define RANGES_V3_RANGE_PRIMITIVES_HPP
16
17#include <concepts/concepts.hpp>
18
20
23#include <range/v3/utility/addressof.hpp>
24#include <range/v3/utility/static_const.hpp>
25
26#include <range/v3/detail/prologue.hpp>
27
28namespace ranges
29{
31 // Specialize this if the default is wrong.
32 template<typename T>
33 RANGES_INLINE_VAR constexpr bool disable_sized_range = false;
34
36 namespace _size_
37 {
38 template<typename T>
39 void size(T &&) = delete;
40
41#ifdef RANGES_WORKAROUND_MSVC_895622
42 void size();
43#endif
44
45 // clang-format off
48 template<typename T>
49 CPP_requires(has_member_size_,
50 requires(T && t) //
51 (
52 ((T &&) t).size()
53 ));
56 template<typename T>
57 CPP_concept has_member_size =
58 CPP_requires_ref(_size_::has_member_size_, T);
59
62 template<typename T>
63 CPP_requires(has_non_member_size_,
64 requires(T && t) //
65 (
66 size((T &&) t)
67 ));
70 template<typename T>
71 CPP_concept has_non_member_size =
72 CPP_requires_ref(_size_::has_non_member_size_, T);
73 // clang-format on
74
75 struct fn
76 {
77 private:
78 struct _member_result_
79 {
80 template<typename R>
81 using invoke = decltype(+(declval(R &).size()));
82 };
83 struct _non_member_result_
84 {
85 template<typename R>
86 using invoke = decltype(+(size(declval(R &))));
87 };
88 struct _distance_result_
89 {
90 template<typename R>
91 using invoke = detail::iter_size_t<_begin_::_t<R>>;
92 };
93 struct _other_result_
94 {
95 template<typename R>
96 using invoke =
99 has_non_member_size<R>,
100 _non_member_result_,
101 _distance_result_>,
102 R>;
103 };
104
105 template<typename R>
106 using _result_t =
109 has_member_size<R>,
110 _member_result_,
111 _other_result_>,
112 R>;
113
114 public:
115 template<typename R, std::size_t N>
116 constexpr std::size_t operator()(R (&)[N], int) const noexcept
117 {
118 return N;
119 }
120
121 template<typename R, std::size_t N>
122 constexpr std::size_t operator()(R(&&)[N]) const noexcept
123 {
124 return N;
125 }
126
127 // Prefer member if it returns integral.
128 template(typename R)(
129 requires (!disable_sized_range<uncvref_t<R>>) AND
130 has_member_size<R> AND detail::integer_like_<_result_t<R>>)
131 constexpr _result_t<R> operator()(R && r) const
132 noexcept(noexcept(((R &&) r).size()))
133 {
134 return ((R &&) r).size();
135 }
136
137 // Use ADL if it returns integral.
138 template(typename R)(
139 requires (!disable_sized_range<uncvref_t<R>>) AND
140 (!has_member_size<R>) AND has_non_member_size<R> AND
141 detail::integer_like_<_result_t<R>>)
142 constexpr _result_t<R> operator()(R && r) const
143 noexcept(noexcept(size((R &&) r)))
144 {
145 return size((R &&) r);
146 }
147
148 template(typename R)(
149 requires (!has_member_size<R> || disable_sized_range<uncvref_t<R>>) AND
150 (!has_non_member_size<R> || disable_sized_range<uncvref_t<R>>) AND
151 forward_iterator<_begin_::_t<R>> AND
152 sized_sentinel_for<_end_::_t<R>, _begin_::_t<R>>)
153 constexpr _result_t<R> operator()(R && r) const
154 noexcept(noexcept(ranges::end((R &&) r) - ranges::begin((R &&) r)))
155 {
156 using size_type = detail::iter_size_t<_begin_::_t<R>>;
157 return static_cast<size_type>(ranges::end((R &&) r) -
158 ranges::begin((R &&) r));
159 }
160 };
161 } // namespace _size_
163
186 RANGES_DEFINE_CPO(_size_::fn, size)
187
188 // Customization point data
190 namespace _data_
191 {
192 // clang-format off
195 template<typename T>
196 CPP_requires(has_member_data_,
197 requires(T & t) //
198 (
199 t.data()
200 ));
203 template<typename T>
204 CPP_concept has_member_data =
205 CPP_requires_ref(_data_::has_member_data_, T);
206 // clang-format on
207
208 struct fn
209 {
210 private:
211 struct _member_data_
212 {
213 template<typename R>
214 using invoke = decltype(+(declval(R &&).data()));
215 };
216 struct _pointer_iterator_
217 {
218 template<typename R>
219 using invoke = _begin_::_t<R>;
220 };
221 struct _contiguous_iterator_
222 {
223 template<typename R>
224 using invoke = decltype(detail::addressof(*declval(_begin_::_t<R> &&)));
225 };
226 struct _other_result_
227 {
228 template<typename R>
229 using invoke =
232 std::is_pointer<_begin_::_t<R>>::value,
233 _pointer_iterator_,
234 _contiguous_iterator_>,
235 R>;
236 };
237
238 template<typename R>
239 using _result_t =
242 has_member_data<R>,
243 _member_data_,
244 _other_result_>,
245 R>;
246
247 public:
248 template(typename R)(
249 requires has_member_data<R &> AND
250 std::is_pointer<_result_t<R &>>::value)
251 constexpr _result_t<R &> operator()(R & r) const //
252 noexcept(noexcept(r.data()))
253 {
254 return r.data();
255 }
256 template(typename R)(
257 requires (!has_member_data<R &>) AND
258 std::is_pointer<_begin_::_t<R>>::value)
259 constexpr _result_t<R> operator()(R && r) const //
260 noexcept(noexcept(ranges::begin((R &&) r)))
261 {
262 return ranges::begin((R &&) r);
263 }
264 template(typename R)(
265 requires (!has_member_data<R &>) AND
266 (!std::is_pointer<_begin_::_t<R>>::value) AND
267 contiguous_iterator<_begin_::_t<R>>)
268 constexpr _result_t<R> operator()(R && r) const //
269 noexcept(noexcept(
270 ranges::begin((R &&) r) == ranges::end((R &&) r)
271 ? nullptr
272 : detail::addressof(*ranges::begin((R &&) r))))
273 {
274 return ranges::begin((R &&) r) == ranges::end((R &&) r)
275 ? nullptr
276 : detail::addressof(*ranges::begin((R &&) r));
277 }
278
279#if RANGES_CXX_STD <= RANGES_CXX_STD_14
280 template<typename charT, typename Traits, typename Alloc>
281 constexpr charT * operator()(
282 std::basic_string<charT, Traits, Alloc> & s) const noexcept
283 {
284 // string doesn't have non-const data before C++17
285 return const_cast<charT *>(detail::as_const(s).data());
286 }
287#endif
288 };
289
290 template<typename R>
291 using _t = decltype(fn{}(declval(R &&)));
292 } // namespace _data_
294
295 RANGES_INLINE_VARIABLE(_data_::fn, data)
296
297
298 namespace _cdata_
299 {
300 struct fn
301 {
302 template<typename R>
303 constexpr _data_::_t<R const &> operator()(R const & r) const
304 noexcept(noexcept(ranges::data(r)))
305 {
306 return ranges::data(r);
307 }
308 template<typename R>
309 constexpr _data_::_t<R const> operator()(R const && r) const
310 noexcept(noexcept(ranges::data((R const &&)r)))
311 {
312 return ranges::data((R const &&)r);
313 }
314 };
315 } // namespace _cdata_
317
322 RANGES_INLINE_VARIABLE(_cdata_::fn, cdata)
323
324
325 namespace _empty_
326 {
327 // clang-format off
330 template<typename T>
331 CPP_requires(has_member_empty_,
332 requires(T && t) //
333 (
334 bool(((T &&) t).empty())
335 ));
338 template<typename T>
339 CPP_concept has_member_empty =
340 CPP_requires_ref(_empty_::has_member_empty_, T);
341
344 template<typename T>
345 CPP_requires(has_size_,
346 requires(T && t) //
347 (
348 ranges::size((T &&) t)
349 ));
352 template<typename T>
353 CPP_concept has_size =
354 CPP_requires_ref(_empty_::has_size_, T);
355 // clang-format on
356
357 struct fn
358 {
359 // Prefer member if it is valid.
360 template(typename R)(
361 requires has_member_empty<R>)
362 constexpr bool operator()(R && r) const
363 noexcept(noexcept(bool(((R &&) r).empty())))
364 {
365 return bool(((R &&) r).empty());
366 }
367
368 // Fall back to size == 0.
369 template(typename R)(
370 requires (!has_member_empty<R>) AND has_size<R>)
371 constexpr bool operator()(R && r) const
372 noexcept(noexcept(bool(ranges::size((R &&) r) == 0)))
373 {
374 return bool(ranges::size((R &&) r) == 0);
375 }
376
377 // Fall further back to begin == end.
378 template(typename R)(
379 requires (!has_member_empty<R>) AND (!has_size<R>) AND
380 forward_iterator<_begin_::_t<R>>)
381 constexpr bool operator()(R && r) const
382 noexcept(noexcept(bool(ranges::begin((R &&) r) == ranges::end((R &&) r))))
383 {
384 return bool(ranges::begin((R &&) r) == ranges::end((R &&) r));
385 }
386 };
387 } // namespace _empty_
389
392 RANGES_INLINE_VARIABLE(_empty_::fn, empty)
393
394 namespace cpp20
395 {
396 // Specialize this is namespace ranges::
397 using ranges::cdata;
398 using ranges::data;
399 using ranges::disable_sized_range;
400 using ranges::empty;
401 using ranges::size;
402 } // namespace cpp20
403} // namespace ranges
404
405#include <range/v3/detail/epilogue.hpp>
406
407#endif
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition meta.hpp:1696
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition meta.hpp:2231
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148