Horizon
primitives.hpp
Go to the documentation of this file.
1 // 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 
19 #include <range/v3/range_fwd.hpp>
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 
28 namespace 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 =
107  meta::invoke<
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 =
230  meta::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 =
240  meta::invoke<
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
CPP_concept sized_sentinel_for
\concept sized_sentinel_for
Definition: concepts.hpp:332
CPP_concept forward_iterator
\concept forward_iterator
Definition: concepts.hpp:370
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
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