Horizon
Loading...
Searching...
No Matches
concepts.hpp
Go to the documentation of this file.
1
2// 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
25
32
33#ifdef _GLIBCXX_DEBUG
34#include <debug/safe_iterator.h>
35#endif
36
37#include <range/v3/detail/prologue.hpp>
38
39namespace 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 = //
153 indirectly_readable<I>;
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>
299 CPP_concept input_or_output_iterator =
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>
390 CPP_concept bidirectional_iterator =
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>
416 CPP_concept random_access_iterator =
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>
545 CPP_concept indirectly_unary_invocable =
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>
564 CPP_concept indirectly_regular_unary_invocable =
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>
632 CPP_concept indirect_unary_predicate =
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>
651 CPP_concept indirect_binary_predicate_ =
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>
689 CPP_concept indirect_strict_weak_order =
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>
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>
768 CPP_concept indirectly_movable_storable =
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 =
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>
798 CPP_concept indirectly_copyable_storable =
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 =
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 =
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 =
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 =
867 CPP_concept_ref(ranges::projected_indirect_strict_weak_order_, C, I, P, I, P);
868 // clang-format on
869
871 {};
874
875 template<typename S, typename I>
876 using sentinel_tag_of = //
877 std::enable_if_t< //
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 {
926 using ranges::indirect_result_t;
941 using ranges::mergeable;
943 using ranges::permutable;
944 using ranges::projected;
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.
958namespace __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
978namespace 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
The bidirectional_iterator_ concept.
The bidirectional_iterator concept.
The contiguous_iterator_ concept.
The contiguous_iterator concept.
The forward_iterator concept.
The incrementable_ concept.
The incrementable concept.
The indirect_binary_predicate_impl_ concept.
The indirect_relation_ concept.
The indirect_relation concept.
The indirect_strict_weak_order_ concept.
The indirect_strict_weak_order concept.
The indirect_unary_predicate_ concept.
The indirect_unary_predicate concept.
The indirectly_comparable concept.
The indirectly_copyable_ concept.
The indirectly_copyable_storable_ concept.
The indirectly_copyable_storable concept.
The indirectly_copyable concept.
The indirectly_movable_ concept.
The indirectly_movable_storable_ concept.
The indirectly_movable_storable concept.
The indirectly_movable concept.
The indirectly_readable concept.
The indirectly_regular_unary_invocable_ concept.
The indirectly_regular_unary_invocable concept.
The indirectly_swappable_ concept.
The indirectly_swappable concept.
The indirectly_unary_invocable concept.
The indirectly_writable concept.
The input_iterator concept.
The input_or_output_iterator_ concept.
The input_or_output_iterator concept.
The output_iterator_ concept.
The output_iterator concept.
The permutable concept.
The projected_indirect_relation_ concept.
The projected_indirect_strict_weak_order_ concept.
The random_access_iterator_ concept.
The random_access_iterator concept.
The readable_ concept.
The sentinel_for concept.
The sized_sentinel_for_ concept.
The sized_sentinel_for concept.
The sortable concept.
The weakly_incrementable_ concept.
The weakly_incrementable concept.
The with_category_ concept.
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
Tiny meta-programming library.
Point operator*(double s, const Point &a)
Multiply point by scalar.
Definition shapes.h:250
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 comparisons.hpp:50
Definition concepts.hpp:871
Definition concepts.hpp:873