Horizon
concepts.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2013-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_ITERATOR_CONCEPTS_HPP
15 #define RANGES_V3_ITERATOR_CONCEPTS_HPP
16 
17 #include <iterator>
18 #include <type_traits>
19 
20 #include <meta/meta.hpp>
21 
22 #include <concepts/concepts.hpp>
23 
24 #include <range/v3/range_fwd.hpp>
25 
32 
33 #ifdef _GLIBCXX_DEBUG
34 #include <debug/safe_iterator.h>
35 #endif
36 
37 #include <range/v3/detail/prologue.hpp>
38 
39 namespace ranges
40 {
43 
45  namespace detail
46  {
47  template<typename I>
49  std::iterator_traits<I>, I>;
50 
51 #if defined(_GLIBCXX_DEBUG)
52  template(typename I, typename T, typename Seq)(
53  requires same_as<I, __gnu_debug::_Safe_iterator<T *, Seq>>)
54  auto iter_concept_(__gnu_debug::_Safe_iterator<T *, Seq>, priority_tag<3>)
56 #endif
57 #if defined(__GLIBCXX__)
58  template(typename I, typename T, typename Seq)(
59  requires same_as<I, __gnu_cxx::__normal_iterator<T *, Seq>>)
60  auto iter_concept_(__gnu_cxx::__normal_iterator<T *, Seq>, priority_tag<3>)
62 #endif
63 #if defined(_LIBCPP_VERSION)
64  template(typename I, typename T)(
65  requires same_as<I, std::__wrap_iter<T *>>)
66  auto iter_concept_(std::__wrap_iter<T *>, priority_tag<3>)
68 #endif
69 #if defined(_MSVC_STL_VERSION) || defined(_IS_WRS)
70  template(typename I)(
71  requires same_as<I, class I::_Array_iterator>)
72  auto iter_concept_(I, priority_tag<3>)
74  template(typename I)(
75  requires same_as<I, class I::_Array_const_iterator>)
76  auto iter_concept_(I, priority_tag<3>)
78  template(typename I)(
79  requires same_as<I, class I::_Vector_iterator>)
80  auto iter_concept_(I, priority_tag<3>)
82  template(typename I)(
83  requires same_as<I, class I::_Vector_const_iterator>)
84  auto iter_concept_(I, priority_tag<3>)
86  template(typename I)(
87  requires same_as<I, class I::_String_iterator>)
88  auto iter_concept_(I, priority_tag<3>)
90  template(typename I)(
91  requires same_as<I, class I::_String_const_iterator>)
92  auto iter_concept_(I, priority_tag<3>)
94  template(typename I)(
95  requires same_as<I, class I::_String_view_iterator>)
96  auto iter_concept_(I, priority_tag<3>)
98 #endif
99  template(typename I, typename T)(
100  requires same_as<I, T *>)
101  auto iter_concept_(T *, priority_tag<3>)
103  template<typename I>
104  auto iter_concept_(I, priority_tag<2>) ->
105  typename iter_traits_t<I>::iterator_concept;
106  template<typename I>
107  auto iter_concept_(I, priority_tag<1>) ->
108  typename iter_traits_t<I>::iterator_category;
109  template<typename I>
110  auto iter_concept_(I, priority_tag<0>)
111  -> enable_if_t<!is_std_iterator_traits_specialized_v<I>,
112  std::random_access_iterator_tag>;
113 
114  template<typename I>
115  using iter_concept_t =
116  decltype(iter_concept_<I>(std::declval<I>(), priority_tag<3>{}));
117 
118  using ::concepts::detail::weakly_equality_comparable_with_;
119 
120  template<typename I>
121  using readable_types_t =
122  meta::list<iter_value_t<I>, iter_reference_t<I>, iter_rvalue_reference_t<I>>;
123  } // namespace detail
125 
126  // clang-format off
129  template(typename I)(
130  concept (readable_)(I),
131  // requires (I const i)
132  // (
133  // { *i } -> same_as<iter_reference_t<I>>;
134  // { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>;
135  // ) &&
136  same_as<iter_reference_t<I const>, iter_reference_t<I>> AND
137  same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>> AND
138  common_reference_with<iter_reference_t<I> &&, iter_value_t<I> &> AND
139  common_reference_with<iter_reference_t<I> &&,
140  iter_rvalue_reference_t<I> &&> AND
141  common_reference_with<iter_rvalue_reference_t<I> &&, iter_value_t<I> const &>
142  );
143 
146  template<typename I>
147  CPP_concept indirectly_readable = //
148  CPP_concept_ref(ranges::readable_, uncvref_t<I>);
149 
150  template<typename I>
151  RANGES_DEPRECATED("Please use ranges::indirectly_readable instead")
152  RANGES_INLINE_VAR constexpr bool readable = //
154 
157  template<typename O, typename T>
158  CPP_requires(writable_,
159  requires(O && o, T && t) //
160  (
161  *o = (T &&) t,
162  *(O &&) o = (T &&) t,
163  const_cast<iter_reference_t<O> const &&>(*o) = (T &&) t,
164  const_cast<iter_reference_t<O> const &&>(*(O &&) o) = (T &&) t
165  ));
168  template<typename O, typename T>
169  CPP_concept indirectly_writable = //
170  CPP_requires_ref(ranges::writable_, O, T);
171 
172  template<typename O, typename T>
173  RANGES_DEPRECATED("Please use ranges::indirectly_writable instead")
174  RANGES_INLINE_VAR constexpr bool writable = //
175  indirectly_writable<O, T>;
176  // clang-format on
177 
179  namespace detail
180  {
181 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
182  template<typename D>
183  inline constexpr bool _is_integer_like_ = std::is_integral<D>::value;
184 #else
185  template<typename D, typename = void>
186  constexpr bool _is_integer_like_ = std::is_integral<D>::value;
187 #endif
188 
189  // gcc10 uses for std::ranges::range_difference_t<
190  // std::ranges::iota_view<size_t, size_t>> == __int128
191 #if __SIZEOF_INT128__
192  __extension__ typedef __int128 int128_t;
193 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
194  template<>
195  inline constexpr bool _is_integer_like_<int128_t> = true;
196 #else
197  template<typename Enable>
198  constexpr bool _is_integer_like_<int128_t, Enable> = true;
199 #endif
200 #endif // __SIZEOF_INT128__
201 
202  // clang-format off
205  template<typename D>
206  CPP_concept integer_like_ = _is_integer_like_<D>;
207  // TODO additional syntactic and semantic requirements
208 
209 #ifdef RANGES_WORKAROUND_MSVC_792338
210  template<typename D, bool Signed = (D(-1) < D(0))>
211  constexpr bool _is_signed_(D *)
212  {
213  return Signed;
214  }
215  constexpr bool _is_signed_(void *)
216  {
217  return false;
218  }
219 
222  template<typename D>
223  CPP_concept signed_integer_like_ =
224  integer_like_<D> && detail::_is_signed_((D*) nullptr);
225 #else // ^^^ workaround / no workaround vvv
228  template(typename D)(
229  concept (signed_integer_like_impl_)(D),
230  integer_like_<D> AND
231  concepts::type<std::integral_constant<bool, (D(-1) < D(0))>> AND
232  std::integral_constant<bool, (D(-1) < D(0))>::value
233  );
234 
237  template<typename D>
238  CPP_concept signed_integer_like_ =
239  integer_like_<D> &&
240  CPP_concept_ref(detail::signed_integer_like_impl_, D);
241 #endif // RANGES_WORKAROUND_MSVC_792338
242  // clang-format on
243  } // namespace detail
245 
246  // clang-format off
249  template<typename I>
250  CPP_requires(weakly_incrementable_,
251  requires(I i) //
252  (
253  ++i,
254  i++,
255  concepts::requires_<same_as<I&, decltype(++i)>>
256  ));
257 
260  template(typename I)(
261  concept (weakly_incrementable_)(I),
262  concepts::type<iter_difference_t<I>> AND
263  detail::signed_integer_like_<iter_difference_t<I>>);
264 
267  template<typename I>
268  CPP_concept weakly_incrementable =
269  copyable<I> &&
270  CPP_requires_ref(ranges::weakly_incrementable_, I) &&
271  CPP_concept_ref(ranges::weakly_incrementable_, I);
272 
275  template<typename I>
276  CPP_requires(incrementable_,
277  requires(I i) //
278  (
279  concepts::requires_<same_as<I, decltype(i++)>>
280  ));
283  template<typename I>
284  CPP_concept incrementable =
285  regular<I> &&
286  weakly_incrementable<I> &&
287  CPP_requires_ref(ranges::incrementable_, I);
288 
291  template(typename I)(
292  concept (input_or_output_iterator_)(I),
293  detail::dereferenceable_<I&>
294  );
295 
298  template<typename I>
300  weakly_incrementable<I> &&
301  CPP_concept_ref(ranges::input_or_output_iterator_, I);
302 
305  template<typename S, typename I>
306  CPP_concept sentinel_for =
307  semiregular<S> &&
308  input_or_output_iterator<I> &&
309  detail::weakly_equality_comparable_with_<S, I>;
310 
313  template<typename S, typename I>
314  CPP_requires(sized_sentinel_for_,
315  requires(S const & s, I const & i) //
316  (
317  s - i,
318  i - s,
319  concepts::requires_<same_as<iter_difference_t<I>, decltype(s - i)>>,
320  concepts::requires_<same_as<iter_difference_t<I>, decltype(i - s)>>
321  ));
324  template(typename S, typename I)(
325  concept (sized_sentinel_for_)(S, I),
326  (!disable_sized_sentinel<std::remove_cv_t<S>, std::remove_cv_t<I>>) AND
327  sentinel_for<S, I>);
328 
331  template<typename S, typename I>
332  CPP_concept sized_sentinel_for =
333  CPP_concept_ref(sized_sentinel_for_, S, I) &&
334  CPP_requires_ref(ranges::sized_sentinel_for_, S, I);
335 
338  template<typename Out, typename T>
339  CPP_requires(output_iterator_,
340  requires(Out o, T && t) //
341  (
342  *o++ = (T &&) t
343  ));
346  template<typename Out, typename T>
347  CPP_concept output_iterator =
348  input_or_output_iterator<Out> &&
349  indirectly_writable<Out, T> &&
350  CPP_requires_ref(ranges::output_iterator_, Out, T);
351 
354  template(typename I, typename Tag)(
355  concept (with_category_)(I, Tag),
356  derived_from<detail::iter_concept_t<I>, Tag>
357  );
358 
361  template<typename I>
362  CPP_concept input_iterator =
363  input_or_output_iterator<I> &&
364  indirectly_readable<I> &&
365  CPP_concept_ref(ranges::with_category_, I, std::input_iterator_tag);
366 
369  template<typename I>
370  CPP_concept forward_iterator =
371  input_iterator<I> &&
372  incrementable<I> &&
373  sentinel_for<I, I> &&
374  CPP_concept_ref(ranges::with_category_, I, std::forward_iterator_tag);
375 
378  template<typename I>
379  CPP_requires(bidirectional_iterator_,
380  requires(I i) //
381  (
382  --i,
383  i--,
384  concepts::requires_<same_as<I&, decltype(--i)>>,
385  concepts::requires_<same_as<I, decltype(i--)>>
386  ));
389  template<typename I>
391  forward_iterator<I> &&
392  CPP_requires_ref(ranges::bidirectional_iterator_, I) &&
393  CPP_concept_ref(ranges::with_category_, I, std::bidirectional_iterator_tag);
394 
397  template<typename I>
398  CPP_requires(random_access_iterator_,
399  requires(I i, iter_difference_t<I> n)
400  (
401  i + n,
402  n + i,
403  i - n,
404  i += n,
405  i -= n,
406  concepts::requires_<same_as<decltype(i + n), I>>,
407  concepts::requires_<same_as<decltype(n + i), I>>,
408  concepts::requires_<same_as<decltype(i - n), I>>,
409  concepts::requires_<same_as<decltype(i += n), I&>>,
410  concepts::requires_<same_as<decltype(i -= n), I&>>,
411  concepts::requires_<same_as<decltype(i[n]), iter_reference_t<I>>>
412  ));
415  template<typename I>
417  bidirectional_iterator<I> &&
418  totally_ordered<I> &&
419  sized_sentinel_for<I, I> &&
420  CPP_requires_ref(ranges::random_access_iterator_, I) &&
421  CPP_concept_ref(ranges::with_category_, I, std::random_access_iterator_tag);
422 
425  template(typename I)(
426  concept (contiguous_iterator_)(I),
427  std::is_lvalue_reference<iter_reference_t<I>>::value AND
428  same_as<iter_value_t<I>, uncvref_t<iter_reference_t<I>>> AND
429  derived_from<detail::iter_concept_t<I>, ranges::contiguous_iterator_tag>
430  );
431 
434  template<typename I>
435  CPP_concept contiguous_iterator =
436  random_access_iterator<I> &&
437  CPP_concept_ref(ranges::contiguous_iterator_, I);
438  // clang-format on
439 
441  // iterator_tag_of
442  template<typename Rng>
443  using iterator_tag_of = //
444  std::enable_if_t< //
445  input_iterator<Rng>, //
447  contiguous_iterator<Rng>, //
450  random_access_iterator<Rng>, //
451  std::random_access_iterator_tag, //
453  bidirectional_iterator<Rng>, //
454  std::bidirectional_iterator_tag, //
456  forward_iterator<Rng>, //
457  std::forward_iterator_tag, //
458  std::input_iterator_tag>>>>>;
459 
461  namespace detail
462  {
463  template<typename, bool>
464  struct iterator_category_
465  {};
466 
467  template<typename I>
468  struct iterator_category_<I, true>
469  {
470  using type = iterator_tag_of<I>;
471  };
472 
473  template<typename T, typename U = meta::_t<std::remove_const<T>>>
474  using iterator_category = iterator_category_<U, (bool)input_iterator<U>>;
475  } // namespace detail
477 
479  // Generally useful to know if an iterator is single-pass or not:
480  // clang-format off
483  template<typename I>
484  CPP_concept single_pass_iterator_ =
485  input_or_output_iterator<I> && !forward_iterator<I>;
486  // clang-format on
488 
490  // indirect_result_t
491  template<typename Fun, typename... Is>
492  using indirect_result_t =
493  detail::enable_if_t<(bool)and_v<(bool)indirectly_readable<Is>...>,
494  invoke_result_t<Fun, iter_reference_t<Is>...>>;
495 
497  namespace detail
498  {
499  // clang-format off
502  template(typename T1, typename T2, typename T3, typename T4)(
503  concept (common_reference_with_4_impl_)(T1, T2, T3, T4),
504  concepts::type<common_reference_t<T1, T2, T3, T4>> AND
505  convertible_to<T1, common_reference_t<T1, T2, T3, T4>> AND
506  convertible_to<T2, common_reference_t<T1, T2, T3, T4>> AND
507  convertible_to<T3, common_reference_t<T1, T2, T3, T4>> AND
508  convertible_to<T4, common_reference_t<T1, T2, T3, T4>>
509  );
510 
513  template<typename T1, typename T2, typename T3, typename T4>
514  CPP_concept common_reference_with_4_ =
515  CPP_concept_ref(detail::common_reference_with_4_impl_, T1, T2, T3, T4);
516  // axiom: all permutations of T1,T2,T3,T4 have the same
517  // common reference type.
518 
521  template(typename F, typename I)(
522  concept (indirectly_unary_invocable_impl_)(F, I),
523  invocable<F &, iter_value_t<I> &> AND
524  invocable<F &, iter_reference_t<I>> AND
525  invocable<F &, iter_common_reference_t<I>> AND
526  common_reference_with<
527  invoke_result_t<F &, iter_value_t<I> &>,
528  invoke_result_t<F &, iter_reference_t<I>>>
529  );
530 
533  template<typename F, typename I>
534  CPP_concept indirectly_unary_invocable_ =
535  indirectly_readable<I> &&
536  CPP_concept_ref(detail::indirectly_unary_invocable_impl_, F, I);
537  // clang-format on
538  } // namespace detail
540 
541  // clang-format off
544  template<typename F, typename I>
546  detail::indirectly_unary_invocable_<F, I> &&
547  copy_constructible<F>;
548 
551  template(typename F, typename I)(
552  concept (indirectly_regular_unary_invocable_)(F, I),
553  regular_invocable<F &, iter_value_t<I> &> AND
554  regular_invocable<F &, iter_reference_t<I>> AND
555  regular_invocable<F &, iter_common_reference_t<I>> AND
556  common_reference_with<
557  invoke_result_t<F &, iter_value_t<I> &>,
558  invoke_result_t<F &, iter_reference_t<I>>>
559  );
560 
563  template<typename F, typename I>
565  indirectly_readable<I> &&
566  copy_constructible<F> &&
567  CPP_concept_ref(ranges::indirectly_regular_unary_invocable_, F, I);
568 
570  // Non-standard indirect invocable concepts
573  template(typename F, typename I1, typename I2)(
574  concept (indirectly_binary_invocable_impl_)(F, I1, I2),
575  invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
576  invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
577  invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
578  invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
579  invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> AND
580  detail::common_reference_with_4_<
581  invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
582  invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
583  invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
584  invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
585  );
586 
589  template<typename F, typename I1, typename I2>
590  CPP_concept indirectly_binary_invocable_ =
591  indirectly_readable<I1> && indirectly_readable<I2> &&
592  copy_constructible<F> &&
593  CPP_concept_ref(ranges::indirectly_binary_invocable_impl_, F, I1, I2);
594 
597  template(typename F, typename I1, typename I2)(
598  concept (indirectly_regular_binary_invocable_impl_)(F, I1, I2),
599  regular_invocable<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
600  regular_invocable<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
601  regular_invocable<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
602  regular_invocable<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
603  regular_invocable<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>> AND
604  detail::common_reference_with_4_<
605  invoke_result_t<F &, iter_value_t<I1> &, iter_value_t<I2> &>,
606  invoke_result_t<F &, iter_value_t<I1> &, iter_reference_t<I2>>,
607  invoke_result_t<F &, iter_reference_t<I1>, iter_value_t<I2> &>,
608  invoke_result_t<F &, iter_reference_t<I1>, iter_reference_t<I2>>>
609  );
610 
613  template<typename F, typename I1, typename I2>
614  CPP_concept indirectly_regular_binary_invocable_ =
615  indirectly_readable<I1> && indirectly_readable<I2> &&
616  copy_constructible<F> &&
617  CPP_concept_ref(ranges::indirectly_regular_binary_invocable_impl_, F, I1, I2);
619 
622  template(typename F, typename I)(
623  concept (indirect_unary_predicate_)(F, I),
624  predicate<F &, iter_value_t<I> &> AND
625  predicate<F &, iter_reference_t<I>> AND
626  predicate<F &, iter_common_reference_t<I>>
627  );
628 
631  template<typename F, typename I>
633  indirectly_readable<I> &&
634  copy_constructible<F> &&
635  CPP_concept_ref(ranges::indirect_unary_predicate_, F, I);
636 
639  template(typename F, typename I1, typename I2)(
640  concept (indirect_binary_predicate_impl_)(F, I1, I2),
641  predicate<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
642  predicate<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
643  predicate<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
644  predicate<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
645  predicate<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
646  );
647 
650  template<typename F, typename I1, typename I2>
652  indirectly_readable<I1> && indirectly_readable<I2> &&
653  copy_constructible<F> &&
654  CPP_concept_ref(ranges::indirect_binary_predicate_impl_, F, I1, I2);
655 
658  template(typename F, typename I1, typename I2)(
659  concept (indirect_relation_)(F, I1, I2),
660  relation<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
661  relation<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
662  relation<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
663  relation<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
664  relation<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
665  );
666 
669  template<typename F, typename I1, typename I2 = I1>
670  CPP_concept indirect_relation =
671  indirectly_readable<I1> && indirectly_readable<I2> &&
672  copy_constructible<F> &&
673  CPP_concept_ref(ranges::indirect_relation_, F, I1, I2);
674 
677  template(typename F, typename I1, typename I2)(
678  concept (indirect_strict_weak_order_)(F, I1, I2),
679  strict_weak_order<F &, iter_value_t<I1> &, iter_value_t<I2> &> AND
680  strict_weak_order<F &, iter_value_t<I1> &, iter_reference_t<I2>> AND
681  strict_weak_order<F &, iter_reference_t<I1>, iter_value_t<I2> &> AND
682  strict_weak_order<F &, iter_reference_t<I1>, iter_reference_t<I2>> AND
683  strict_weak_order<F &, iter_common_reference_t<I1>, iter_common_reference_t<I2>>
684  );
685 
688  template<typename F, typename I1, typename I2 = I1>
690  indirectly_readable<I1> && indirectly_readable<I2> &&
691  copy_constructible<F> &&
692  CPP_concept_ref(ranges::indirect_strict_weak_order_, F, I1, I2);
693  // clang-format on
694 
696  // projected struct, for "projecting" a readable with a unary callable
698  namespace detail
699  {
700  RANGES_DIAGNOSTIC_PUSH
701  RANGES_DIAGNOSTIC_IGNORE_UNDEFINED_INTERNAL
702  template<typename I, typename Proj>
703  struct projected_
704  {
705  struct type
706  {
707  using reference = indirect_result_t<Proj &, I>;
708  using value_type = uncvref_t<reference>;
709  reference operator*() const;
710  };
711  };
712  RANGES_DIAGNOSTIC_POP
713 
714  template<typename Proj>
715  struct select_projected_
716  {
717  template<typename I>
718  using apply =
719  meta::_t<
720  detail::enable_if_t<
721  (bool)indirectly_regular_unary_invocable<Proj, I>,
722  detail::projected_<I, Proj>>>;
723  };
724 
725  template<>
726  struct select_projected_<identity>
727  {
728  template<typename I>
729  using apply = detail::enable_if_t<(bool)indirectly_readable<I>, I>;
730  };
731  } // namespace detail
733 
734  template<typename I, typename Proj>
735  using projected = typename detail::select_projected_<Proj>::template apply<I>;
736 
737  template<typename I, typename Proj>
739  {};
740 
741  // clang-format off
744  template(typename I, typename O)(
745  concept (indirectly_movable_)(I, O),
746  indirectly_writable<O, iter_rvalue_reference_t<I>>
747  );
748 
751  template<typename I, typename O>
752  CPP_concept indirectly_movable =
753  indirectly_readable<I> && CPP_concept_ref(ranges::indirectly_movable_, I, O);
754 
757  template(typename I, typename O)(
758  concept (indirectly_movable_storable_)(I, O),
759  indirectly_writable<O, iter_value_t<I>> AND
760  movable<iter_value_t<I>> AND
761  constructible_from<iter_value_t<I>, iter_rvalue_reference_t<I>> AND
762  assignable_from<iter_value_t<I> &, iter_rvalue_reference_t<I>>
763  );
764 
767  template<typename I, typename O>
769  indirectly_movable<I, O> &&
770  CPP_concept_ref(ranges::indirectly_movable_storable_, I, O);
771 
774  template(typename I, typename O)(
775  concept (indirectly_copyable_)(I, O),
776  indirectly_writable<O, iter_reference_t<I>>
777  );
778 
781  template<typename I, typename O>
782  CPP_concept indirectly_copyable =
783  indirectly_readable<I> && CPP_concept_ref(ranges::indirectly_copyable_, I, O);
784 
787  template(typename I, typename O)(
788  concept (indirectly_copyable_storable_)(I, O),
789  indirectly_writable<O, iter_value_t<I> const &> AND
790  copyable<iter_value_t<I>> AND
791  constructible_from<iter_value_t<I>, iter_reference_t<I>> AND
792  assignable_from<iter_value_t<I> &, iter_reference_t<I>>
793  );
794 
797  template<typename I, typename O>
799  indirectly_copyable<I, O> &&
800  CPP_concept_ref(ranges::indirectly_copyable_storable_, I, O);
801 
804  template<typename I1, typename I2>
805  CPP_requires(indirectly_swappable_,
806  requires(I1 const i1, I2 const i2) //
807  (
808  ranges::iter_swap(i1, i2),
809  ranges::iter_swap(i1, i1),
810  ranges::iter_swap(i2, i2),
811  ranges::iter_swap(i2, i1)
812  ));
815  template<typename I1, typename I2 = I1>
816  CPP_concept indirectly_swappable =
817  indirectly_readable<I1> && //
818  indirectly_readable<I2> && //
819  CPP_requires_ref(ranges::indirectly_swappable_, I1, I2);
820 
823  template(typename C, typename I1, typename P1, typename I2, typename P2)(
824  concept (projected_indirect_relation_)(C, I1, P1, I2, P2),
825  indirect_relation<C, projected<I1, P1>, projected<I2, P2>>
826  );
827 
830  template<typename I1, typename I2, typename C, typename P1 = identity,
831  typename P2 = identity>
832  CPP_concept indirectly_comparable =
833  CPP_concept_ref(ranges::projected_indirect_relation_, C, I1, P1, I2, P2);
834 
836  // Composite concepts for use defining algorithms:
839  template<typename I>
840  CPP_concept permutable =
841  forward_iterator<I> &&
842  indirectly_swappable<I, I> &&
843  indirectly_movable_storable<I, I>;
844 
847  template(typename C, typename I1, typename P1, typename I2, typename P2)(
848  concept (projected_indirect_strict_weak_order_)(C, I1, P1, I2, P2),
849  indirect_strict_weak_order<C, projected<I1, P1>, projected<I2, P2>>
850  );
851 
852  template<typename I1, typename I2, typename Out, typename C = less,
853  typename P1 = identity, typename P2 = identity>
854  CPP_concept mergeable =
855  input_iterator<I1> &&
856  input_iterator<I2> &&
857  weakly_incrementable<Out> &&
858  indirectly_copyable<I1, Out> &&
859  indirectly_copyable<I2, Out> &&
860  CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I1, P1, I2, P2);
861 
864  template<typename I, typename C = less, typename P = identity>
865  CPP_concept sortable =
866  permutable<I> &&
867  CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I, P, I, P);
868  // clang-format on
869 
871  {};
873  {};
874 
875  template<typename S, typename I>
876  using sentinel_tag_of = //
877  std::enable_if_t< //
878  sentinel_for<S, I>, //
880  sized_sentinel_for<S, I>, //
882  sentinel_tag>>;
883 
884  // Deprecated things:
886  template<typename I>
887  using iterator_category RANGES_DEPRECATED(
888  "iterator_category is deprecated. Use the iterator concepts instead") =
889  detail::iterator_category<I>;
890 
891  template<typename I>
892  using iterator_category_t RANGES_DEPRECATED(
893  "iterator_category_t is deprecated. Use the iterator concepts instead") =
895 
896  template<typename Fun, typename... Is>
897  using indirect_invoke_result_t RANGES_DEPRECATED(
898  "Please switch to indirect_result_t") = indirect_result_t<Fun, Is...>;
899 
900  template<typename Fun, typename... Is>
901  struct RANGES_DEPRECATED("Please switch to indirect_result_t") indirect_invoke_result
902  : meta::defer<indirect_result_t, Fun, Is...>
903  {};
904 
905  template<typename Sig>
906  struct indirect_result_of
907  {};
908 
909  template<typename Fun, typename... Is>
910  struct RANGES_DEPRECATED("Please switch to indirect_result_t")
911  indirect_result_of<Fun(Is...)> : meta::defer<indirect_result_t, Fun, Is...>
912  {};
913 
914  template<typename Sig>
915  using indirect_result_of_t RANGES_DEPRECATED("Please switch to indirect_result_t") =
918 
919  namespace cpp20
920  {
924  using ranges::incrementable;
926  using ranges::indirect_result_t;
941  using ranges::mergeable;
943  using ranges::permutable;
944  using ranges::projected;
946  using ranges::sentinel_for;
948  using ranges::sortable;
950  } // namespace cpp20
952 } // namespace ranges
953 
954 #ifdef _GLIBCXX_DEBUG
955 // HACKHACK: workaround underconstrained operator- for libstdc++ debug iterator wrapper
956 // by intentionally creating an ambiguity when the wrapped types don't support the
957 // necessary operation.
958 namespace __gnu_debug
959 {
960  template(typename I1, typename I2, typename Seq)(
961  requires (!::ranges::sized_sentinel_for<I1, I2>)) //
962  void operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I2, Seq> const &) =
963  delete;
964 
965  template(typename I1, typename Seq)(
966  requires (!::ranges::sized_sentinel_for<I1, I1>)) //
967  void operator-(_Safe_iterator<I1, Seq> const &, _Safe_iterator<I1, Seq> const &) =
968  delete;
969 } // namespace __gnu_debug
970 #endif
971 
972 #if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
973 // HACKHACK: workaround libc++ (https://llvm.org/bugs/show_bug.cgi?id=28421)
974 // and libstdc++ (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71771)
975 // underconstrained operator- for reverse_iterator by disabling sized_sentinel_for
976 // when the base iterators do not model sized_sentinel_for.
977 
978 namespace ranges
979 {
980  template<typename S, typename I>
981  /*inline*/ constexpr bool
982  disable_sized_sentinel<std::reverse_iterator<S>, std::reverse_iterator<I>> =
983  !static_cast<bool>(sized_sentinel_for<I, S>);
984 } // namespace ranges
985 
986 #endif // defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 3900)
987 
988 #include <range/v3/detail/epilogue.hpp>
989 
990 #endif // RANGES_V3_ITERATOR_CONCEPTS_HPP
CPP_concept invocable
\concept invocable
Definition: concepts.hpp:48
CPP_concept regular_invocable
\concept regular_invocable
Definition: concepts.hpp:55
CPP_concept strict_weak_order
\concept strict_weak_order
Definition: concepts.hpp:89
CPP_concept predicate
\concept predicate
Definition: concepts.hpp:73
CPP_concept relation
\concept relation
Definition: concepts.hpp:80
CPP_concept indirectly_swappable
\concept indirectly_swappable
Definition: concepts.hpp:816
CPP_concept indirectly_unary_invocable
\concept indirectly_unary_invocable
Definition: concepts.hpp:545
CPP_concept permutable
\concept permutable
Definition: concepts.hpp:840
CPP_concept sentinel_for
\concept sentinel_for
Definition: concepts.hpp:306
CPP_concept output_iterator
\concept output_iterator
Definition: concepts.hpp:347
CPP_concept indirect_unary_predicate
\concept indirect_unary_predicate
Definition: concepts.hpp:632
CPP_concept indirectly_comparable
\concept indirectly_comparable
Definition: concepts.hpp:832
CPP_concept input_iterator
\concept input_iterator
Definition: concepts.hpp:362
CPP_concept indirect_relation
\concept indirect_relation
Definition: concepts.hpp:670
CPP_concept indirectly_movable
\concept indirectly_movable
Definition: concepts.hpp:752
CPP_concept bidirectional_iterator
\concept bidirectional_iterator
Definition: concepts.hpp:390
CPP_concept indirectly_writable
\concept indirectly_writable
Definition: concepts.hpp:169
CPP_concept incrementable
\concept incrementable
Definition: concepts.hpp:284
CPP_concept sortable
\concept sortable
Definition: concepts.hpp:865
CPP_concept indirect_binary_predicate_
\concept indirect_binary_predicate_
Definition: concepts.hpp:651
CPP_concept contiguous_iterator
\concept contiguous_iterator
Definition: concepts.hpp:435
CPP_concept input_or_output_iterator
\concept input_or_output_iterator
Definition: concepts.hpp:299
CPP_concept sized_sentinel_for
\concept sized_sentinel_for
Definition: concepts.hpp:332
CPP_concept indirectly_movable_storable
\concept indirectly_movable_storable
Definition: concepts.hpp:768
CPP_concept forward_iterator
\concept forward_iterator
Definition: concepts.hpp:370
CPP_concept indirectly_readable
\concept indirectly_readable
Definition: concepts.hpp:147
CPP_concept indirect_strict_weak_order
\concept indirect_strict_weak_order
Definition: concepts.hpp:689
CPP_concept indirectly_regular_unary_invocable
\concept indirectly_regular_unary_invocable
Definition: concepts.hpp:564
CPP_concept indirectly_copyable_storable
\concept indirectly_copyable_storable
Definition: concepts.hpp:798
CPP_concept random_access_iterator
\concept random_access_iterator
Definition: concepts.hpp:416
CPP_concept indirectly_copyable
\concept indirectly_copyable
Definition: concepts.hpp:782
CPP_concept weakly_incrementable
\concept weakly_incrementable
Definition: concepts.hpp:268
template(typename T, typename V)(concept(output_range_)(T
\concept output_range_
CPP_requires(sized_range_, requires(T &t)(ranges::size(t)))
\concept sized_range_
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
_t< extension::apply< Fn, L > > apply
Applies the invocable Fn using the types in the type list L as arguments.
Definition: meta.hpp:1030
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
bool_<(T::type::value< U::type::value)> less
A Boolean integral constant wrapper around true if T::type::value is less than U::type::value; false,...
Definition: meta.hpp:255
Tiny meta-programming library.
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition: meta.hpp:787
A list of types.
Definition: meta.hpp:1684
Definition: traits.hpp:48
Definition: identity.hpp:25
Definition: associated_types.hpp:166
Definition: pipeable.hpp:76
Definition: concepts.hpp:871
Definition: concepts.hpp:873