File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/librangeV3.x/i/range/v3/utility/basic_iterator.hpp
Criterion Covered Total %
statement 19 19 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 19 19 100.0


line stmt bran cond sub pod time code
1             /// \file
2             // Range v3 library
3             //
4             // Copyright Eric Niebler 2014-present
5             // Copyright Casey Carter 2016
6             //
7             // Use, modification and distribution is subject to the
8             // Boost Software License, Version 1.0. (See accompanying
9             // file LICENSE_1_0.txt or copy at
10             // http://www.boost.org/LICENSE_1_0.txt)
11             //
12             // Project home: https://github.com/ericniebler/range-v3
13             //
14             #ifndef RANGES_V3_UTILITY_BASIC_ITERATOR_HPP
15             #define RANGES_V3_UTILITY_BASIC_ITERATOR_HPP
16              
17             #include
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24             #include
25             #include
26             #include
27             #include
28             #include
29             #include
30              
31             namespace ranges
32             {
33             inline namespace v3
34             {
35             /// \addtogroup group-utility Utility
36             /// @{
37             ///
38             template
39             struct basic_mixin : private box
40             {
41             CONCEPT_REQUIRES(DefaultConstructible())
42             constexpr basic_mixin()
43             noexcept(std::is_nothrow_default_constructible::value)
44             : box{}
45             {}
46             CONCEPT_REQUIRES(MoveConstructible())
47 1276           explicit constexpr basic_mixin(T &&t)
48             noexcept(std::is_nothrow_move_constructible::value)
49 1276           : box(detail::move(t))
50 1276           {}
51             CONCEPT_REQUIRES(CopyConstructible())
52             explicit constexpr basic_mixin(T const &t)
53             noexcept(std::is_nothrow_copy_constructible::value)
54             : box(t)
55             {}
56             protected:
57             using box::get;
58             };
59              
60             /// \cond
61             namespace detail
62             {
63             template
64             using cursor_reference_t =
65             decltype(range_access::read(std::declval()));
66              
67             // Compute the rvalue reference type of a cursor
68             template
69             auto cursor_move(Cur const &cur, int) ->
70             decltype(range_access::move(cur));
71             template
72             auto cursor_move(Cur const &cur, long) ->
73             aux::move_t>;
74              
75             template
76             using cursor_rvalue_reference_t =
77             decltype(detail::cursor_move(std::declval(), 42));
78              
79             // Define conversion operators from the proxy reference type
80             // to the common reference types, so that basic_iterator can model Readable
81             // even with getters/setters.
82             template
83             struct proxy_reference_conversion
84             {
85             operator Head() const
86             noexcept(noexcept(Head(Head(std::declval().read_()))))
87             {
88             return Head(static_cast(this)->read_());
89             }
90             };
91              
92             // Collect the reference types associated with cursors
93             template()>
94             struct cursor_traits
95             {
96             private:
97             struct private_ {};
98             public:
99             using value_t_ = private_;
100             using reference_t_ = private_;
101             using rvalue_reference_t_ = private_;
102             using common_refs = meta::list<>;
103             };
104              
105             template
106             struct cursor_traits
107             {
108             using value_t_ = range_access::cursor_value_t;
109             using reference_t_ = cursor_reference_t;
110             using rvalue_reference_t_ = cursor_rvalue_reference_t;
111             private:
112             using R1 = reference_t_;
113             using R2 = common_reference_t;
114             using R3 = common_reference_t;
115             using tmp1 = meta::list;
116             using tmp2 =
117             meta::if_>, tmp1, meta::push_back>;
118             using tmp3 =
119             meta::if_>, tmp2, meta::push_back>;
120             public:
121             using common_refs = meta::unique>;
122             };
123              
124             // The One Proxy Reference type to rule them all. basic_iterator uses this
125             // as the return type of operator* when the cursor type has a set() member
126             // function of the correct signature (i.e., if it can accept a value_type &&).
127             template()>
128             struct RANGES_EMPTY_BASES basic_proxy_reference
129             : cursor_traits
130             // The following adds conversion operators to the common reference
131             // types, so that basic_proxy_reference can model Readable
132             , meta::inherit<
133             meta::transform<
134             typename cursor_traits::common_refs,
135             meta::bind_front<
136             meta::quote,
137             basic_proxy_reference>>>
138             {
139             private:
140             Cur *cur_;
141             template
142             friend struct basic_proxy_reference;
143             template
144             friend struct proxy_reference_conversion;
145             using typename cursor_traits::value_t_;
146             using typename cursor_traits::reference_t_;
147             using typename cursor_traits::rvalue_reference_t_;
148             CONCEPT_ASSERT_MSG(CommonReference(),
149             "Your readable and writable cursor must have a value type and a reference "
150             "type that share a common reference type. See the ranges::common_reference "
151             "type trait.");
152             RANGES_CXX14_CONSTEXPR
153             reference_t_ read_() const
154             noexcept(noexcept(reference_t_(range_access::read(std::declval()))))
155             {
156             return range_access::read(*cur_);
157             }
158             template
159             RANGES_CXX14_CONSTEXPR
160             void write_(T && t) const
161             {
162             range_access::write(*cur_, (T &&) t);
163             }
164             public:
165             basic_proxy_reference() = default;
166             basic_proxy_reference(basic_proxy_reference const &) = default;
167             template
168             CONCEPT_REQUIRES_(ConvertibleTo())>
169             RANGES_CXX14_CONSTEXPR
170             basic_proxy_reference(basic_proxy_reference const &that) noexcept
171             : cur_(that.cur_)
172             {}
173             RANGES_CXX14_CONSTEXPR
174             explicit basic_proxy_reference(Cur &cur) noexcept
175             : cur_(&cur)
176             {}
177             CONCEPT_REQUIRES(ReadableCursor())
178             RANGES_CXX14_CONSTEXPR
179             basic_proxy_reference &operator=(basic_proxy_reference && that)
180             {
181             return *this = that;
182             }
183             CONCEPT_REQUIRES(ReadableCursor())
184             RANGES_CXX14_CONSTEXPR
185             basic_proxy_reference &operator=(basic_proxy_reference const &that)
186             {
187             this->write_(that.read_());
188             return *this;
189             }
190             CONCEPT_REQUIRES(ReadableCursor())
191             RANGES_CXX14_CONSTEXPR
192             basic_proxy_reference const &operator=(basic_proxy_reference && that) const
193             {
194             return *this = that;
195             }
196             CONCEPT_REQUIRES(ReadableCursor())
197             RANGES_CXX14_CONSTEXPR
198             basic_proxy_reference const &operator=(basic_proxy_reference const &that) const
199             {
200             this->write_(that.read_());
201             return *this;
202             }
203             template
204             CONCEPT_REQUIRES_(ReadableCursor() &&
205             WritableCursor>())>
206             RANGES_CXX14_CONSTEXPR
207             basic_proxy_reference &operator=(basic_proxy_reference && that)
208             {
209             return *this = that;
210             }
211             template
212             CONCEPT_REQUIRES_(ReadableCursor() &&
213             WritableCursor>())>
214             RANGES_CXX14_CONSTEXPR
215             basic_proxy_reference &operator=(basic_proxy_reference const &that)
216             {
217             this->write_(that.read_());
218             return *this;
219             }
220             template
221             CONCEPT_REQUIRES_(ReadableCursor() &&
222             WritableCursor>())>
223             RANGES_CXX14_CONSTEXPR
224             basic_proxy_reference const &operator=(basic_proxy_reference && that) const
225             {
226             return *this = that;
227             }
228             template
229             CONCEPT_REQUIRES_(ReadableCursor() &&
230             WritableCursor>())>
231             RANGES_CXX14_CONSTEXPR
232             basic_proxy_reference const &operator=(basic_proxy_reference const &that) const
233             {
234             this->write_(that.read_());
235             return *this;
236             }
237             template
238             CONCEPT_REQUIRES_(WritableCursor())>
239             RANGES_CXX14_CONSTEXPR
240             basic_proxy_reference &operator=(T && t)
241             {
242             this->write_((T &&) t);
243             return *this;
244             }
245             template
246             CONCEPT_REQUIRES_(WritableCursor())>
247             RANGES_CXX14_CONSTEXPR
248             basic_proxy_reference const &operator=(T && t) const
249             {
250             this->write_((T &&) t);
251             return *this;
252             }
253             template
254             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
255             RANGES_CXX14_CONSTEXPR
256             friend bool operator==(basic_proxy_reference const &x, value_t_ const &y)
257             {
258             return x.read_() == y;
259             }
260             template
261             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
262             RANGES_CXX14_CONSTEXPR
263             friend bool operator!=(basic_proxy_reference const &x, value_t_ const &y)
264             {
265             return !(x == y);
266             }
267             template
268             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
269             RANGES_CXX14_CONSTEXPR
270             friend bool operator==(value_t_ const &x, basic_proxy_reference const &y)
271             {
272             return x == y.read_();
273             }
274             template
275             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
276             RANGES_CXX14_CONSTEXPR
277             friend bool operator!=(value_t_ const &x, basic_proxy_reference const &y)
278             {
279             return !(x == y);
280             }
281             template
282             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
283             RANGES_CXX14_CONSTEXPR
284             friend bool operator==(basic_proxy_reference const &x, basic_proxy_reference const &y)
285             {
286             return x.read_() == y.read_();
287             }
288             template
289             CONCEPT_REQUIRES_(ReadableCursor() && EqualityComparable())>
290             RANGES_CXX14_CONSTEXPR
291             friend bool operator!=(basic_proxy_reference const &x, basic_proxy_reference const &y)
292             {
293             return !(x == y);
294             }
295             };
296              
297             auto iter_cat(range_access::InputCursor *) ->
298             ranges::input_iterator_tag;
299             auto iter_cat(range_access::ForwardCursor *) ->
300             ranges::forward_iterator_tag;
301             auto iter_cat(range_access::BidirectionalCursor *) ->
302             ranges::bidirectional_iterator_tag;
303             auto iter_cat(range_access::RandomAccessCursor *) ->
304             ranges::random_access_iterator_tag;
305              
306             template()>
307             struct iterator_associated_types_base
308             : range_access::mixin_base_t
309             {
310             protected:
311             using reference_t = basic_proxy_reference;
312             using const_reference_t = basic_proxy_reference;
313             using cursor_concept_t = range_access::OutputCursor;
314             public:
315             using reference = void;
316             using difference_type = range_access::cursor_difference_t;
317              
318             using range_access::mixin_base_t::mixin_base_t;
319             };
320              
321             template
322             using cursor_arrow_t =
323             decltype(range_access::arrow(std::declval()));
324              
325             template
326             struct iterator_associated_types_base
327             : range_access::mixin_base_t
328             {
329             protected:
330             using cursor_concept_t = detail::cursor_concept_t;
331             using reference_t =
332             meta::if_<
333             is_writable_cursor,
334             basic_proxy_reference,
335             meta::if_<
336             is_writable_cursor,
337             basic_proxy_reference,
338             cursor_reference_t>>;
339             using const_reference_t =
340             meta::if_<
341             is_writable_cursor,
342             basic_proxy_reference,
343             cursor_reference_t>;
344             public:
345             using difference_type = range_access::cursor_difference_t;
346             using value_type = range_access::cursor_value_t;
347             using reference = reference_t;
348             using iterator_category =
349             decltype(detail::iter_cat(_nullptr_v()));
350             using pointer = meta::_t
351             HasCursorArrow,
352             meta::defer,
353             std::add_pointer>>;
354             using common_reference = common_reference_t;
355              
356 2552           using range_access::mixin_base_t::mixin_base_t;
357             };
358             }
359             /// \endcond
360              
361             #if RANGES_BROKEN_CPO_LOOKUP
362 1276           namespace _basic_iterator_ { template struct adl_hook {}; }
363             #endif
364              
365             template
366             struct RANGES_EMPTY_BASES basic_iterator
367             : detail::iterator_associated_types_base
368             #if RANGES_BROKEN_CPO_LOOKUP
369             , private _basic_iterator_::adl_hook>
370             #endif
371             {
372             private:
373             template
374             friend struct basic_iterator;
375             friend range_access;
376             using base_t = detail::iterator_associated_types_base;
377             using mixin_t = range_access::mixin_base_t;
378             CONCEPT_ASSERT(detail::Cursor());
379             using assoc_types_ = detail::iterator_associated_types_base;
380             using typename assoc_types_::cursor_concept_t;
381             using typename assoc_types_::reference_t;
382             using typename assoc_types_::const_reference_t;
383 308           RANGES_CXX14_CONSTEXPR Cur &pos() noexcept
384             {
385 308           return this->mixin_t::get();
386             }
387 2200           constexpr Cur const &pos() const noexcept
388             {
389 2200           return this->mixin_t::get();
390             }
391              
392             public:
393             using typename assoc_types_::difference_type;
394             constexpr basic_iterator() = default;
395             template
396             CONCEPT_REQUIRES_(ConvertibleTo() &&
397             Constructible())>
398             RANGES_CXX14_CONSTEXPR
399             basic_iterator(basic_iterator that)
400             : base_t{std::move(that.pos())}
401             {}
402             // Mix in any additional constructors provided by the mixin
403 2552           using base_t::base_t;
404              
405             template
406             CONCEPT_REQUIRES_(!Same, basic_iterator>() &&
407             !detail::HasCursorNext() && detail::WritableCursor())>
408             RANGES_CXX14_CONSTEXPR
409             basic_iterator &operator=(T && t)
410             noexcept(noexcept(std::declval().write(static_cast(t))))
411             {
412             pos().write(static_cast(t));
413             return *this;
414             }
415              
416             template
417             CONCEPT_REQUIRES_(!Same, basic_iterator>() &&
418             !detail::HasCursorNext() && detail::WritableCursor())>
419             RANGES_CXX14_CONSTEXPR
420             basic_iterator const &operator=(T && t) const
421             noexcept(noexcept(std::declval().write(static_cast(t))))
422             {
423             pos().write(static_cast(t));
424             return *this;
425             }
426              
427             CONCEPT_REQUIRES(detail::ReadableCursor() &&
428             !detail::is_writable_cursor())
429 308           constexpr const_reference_t operator*() const
430             noexcept(noexcept(range_access::read(std::declval())))
431             {
432 308           return range_access::read(pos());
433             }
434             CONCEPT_REQUIRES(detail::HasCursorNext() &&
435             detail::is_writable_cursor())
436             RANGES_CXX14_CONSTEXPR reference_t operator*()
437             noexcept(noexcept(reference_t{std::declval()}))
438             {
439             return reference_t{pos()};
440             }
441             CONCEPT_REQUIRES(detail::HasCursorNext() &&
442             detail::is_writable_cursor())
443             constexpr const_reference_t operator*() const
444             noexcept(noexcept(const_reference_t{std::declval()}))
445             {
446             return const_reference_t{pos()};
447             }
448             CONCEPT_REQUIRES(!detail::HasCursorNext())
449             RANGES_CXX14_CONSTEXPR basic_iterator &operator*() noexcept
450             {
451             return *this;
452             }
453              
454             // Use cursor's arrow() member, if any.
455             template
456             CONCEPT_REQUIRES_(detail::HasCursorArrow())>
457             constexpr auto operator->() const
458             noexcept(noexcept(range_access::arrow(std::declval())))
459             -> detail::cursor_arrow_t
460             {
461             return range_access::arrow(pos());
462             }
463             // Otherwise, if reference_t is an lvalue reference to cv-qualified
464             // value_type_t, return the address of **this.
465             template
466             CONCEPT_REQUIRES_(!detail::HasCursorArrow() &&
467             detail::ReadableCursor() &&
468             std::is_lvalue_reference::value &&
469             Same::value_type,
470             uncvref_t>())>
471             constexpr meta::_t>
472             operator->() const
473             noexcept(noexcept(*std::declval()))
474             {
475             return std::addressof(**this);
476             }
477              
478             CONCEPT_REQUIRES(detail::HasCursorNext())
479             RANGES_CXX14_CONSTEXPR
480 308           basic_iterator &operator++()
481             {
482 308           range_access::next(pos());
483 308           return *this;
484             }
485             CONCEPT_REQUIRES(!detail::HasCursorNext())
486             RANGES_CXX14_CONSTEXPR
487             basic_iterator &operator++() noexcept
488             {
489             return *this;
490             }
491              
492             CONCEPT_REQUIRES(!Same>())
493             RANGES_CXX14_CONSTEXPR
494             basic_iterator operator++(int)
495             {
496             basic_iterator tmp{*this};
497             ++*this;
498             return tmp;
499             }
500             CONCEPT_REQUIRES(Same>())
501             RANGES_CXX14_CONSTEXPR
502             void operator++(int)
503             {
504             ++*this;
505             }
506              
507             template())>
508 946           friend constexpr bool operator==(basic_iterator const &left,
509             basic_iterator const &right)
510             {
511 946           return range_access::equal(left.pos(), range_access::pos(right));
512             }
513             template())>
514 473           friend constexpr bool operator!=(basic_iterator const &left,
515             basic_iterator const &right)
516             {
517 473           return !(left == right);
518             }
519             template())>
520             friend constexpr bool operator==(basic_iterator const &left,
521             S const &right)
522             {
523             return range_access::equal(left.pos(), right);
524             }
525             template())>
526             friend constexpr bool operator!=(basic_iterator const &left,
527             S const &right)
528             {
529             return !(left == right);
530             }
531             template())>
532             friend constexpr bool operator==(S const &left,
533             basic_iterator const &right)
534             {
535             return right == left;
536             }
537             template())>
538             friend constexpr bool operator!=(S const &left,
539             basic_iterator const &right)
540             {
541             return right != left;
542             }
543             CONCEPT_REQUIRES(detail::BidirectionalCursor())
544             RANGES_CXX14_CONSTEXPR
545             basic_iterator &operator--()
546             {
547             range_access::prev(pos());
548             return *this;
549             }
550             CONCEPT_REQUIRES(detail::BidirectionalCursor())
551             RANGES_CXX14_CONSTEXPR
552             basic_iterator operator--(int)
553             {
554             basic_iterator tmp(*this);
555             --*this;
556             return tmp;
557             }
558             CONCEPT_REQUIRES(detail::RandomAccessCursor())
559             RANGES_CXX14_CONSTEXPR
560             basic_iterator &operator+=(difference_type n)
561             {
562             range_access::advance(pos(), n);
563             return *this;
564             }
565             CONCEPT_REQUIRES(detail::RandomAccessCursor())
566             RANGES_CXX14_CONSTEXPR
567             friend basic_iterator operator+(basic_iterator left, difference_type n)
568             {
569             left += n;
570             return left;
571             }
572             CONCEPT_REQUIRES(detail::RandomAccessCursor())
573             RANGES_CXX14_CONSTEXPR
574             friend basic_iterator operator+(difference_type n, basic_iterator right)
575             {
576             right += n;
577             return right;
578             }
579             CONCEPT_REQUIRES(detail::RandomAccessCursor())
580             RANGES_CXX14_CONSTEXPR
581             basic_iterator &operator-=(difference_type n)
582             {
583             range_access::advance(pos(), -n);
584             return *this;
585             }
586             CONCEPT_REQUIRES(detail::RandomAccessCursor())
587             RANGES_CXX14_CONSTEXPR
588             friend basic_iterator operator-(basic_iterator left, difference_type n)
589             {
590             left -= n;
591             return left;
592             }
593             template
594             CONCEPT_REQUIRES_(detail::SizedCursorSentinel())>
595             RANGES_CXX14_CONSTEXPR
596             friend difference_type operator-(basic_iterator const &left,
597             basic_iterator const &right)
598             {
599             return range_access::distance_to(right.pos(), range_access::pos(left));
600             }
601             template
602             CONCEPT_REQUIRES_(detail::SizedCursorSentinel())>
603             RANGES_CXX14_CONSTEXPR
604             friend difference_type operator-(S const &left,
605             basic_iterator const &right)
606             {
607             return range_access::distance_to(right.pos(), left);
608             }
609             template
610             CONCEPT_REQUIRES_(detail::SizedCursorSentinel())>
611             RANGES_CXX14_CONSTEXPR
612             friend difference_type operator-(basic_iterator const &left,
613             S const &right)
614             {
615             return -(right - left);
616             }
617             // symmetric comparisons
618             CONCEPT_REQUIRES(detail::SizedCursorSentinel())
619             RANGES_CXX14_CONSTEXPR
620             friend bool operator<(basic_iterator const &left, basic_iterator const &right)
621             {
622             return 0 < (right - left);
623             }
624             CONCEPT_REQUIRES(detail::SizedCursorSentinel())
625             RANGES_CXX14_CONSTEXPR
626             friend bool operator<=(basic_iterator const &left, basic_iterator const &right)
627             {
628             return 0 <= (right - left);
629             }
630             CONCEPT_REQUIRES(detail::SizedCursorSentinel())
631             RANGES_CXX14_CONSTEXPR
632             friend bool operator>(basic_iterator const &left, basic_iterator const &right)
633             {
634             return (right - left) < 0;
635             }
636             CONCEPT_REQUIRES(detail::SizedCursorSentinel())
637             RANGES_CXX14_CONSTEXPR
638             friend bool operator>=(basic_iterator const &left, basic_iterator const &right)
639             {
640             return (right - left) <= 0;
641             }
642             CONCEPT_REQUIRES(detail::RandomAccessCursor())
643             RANGES_CXX14_CONSTEXPR
644             const_reference_t operator[](difference_type n) const
645             {
646             return *(*this + n);
647             }
648              
649             #if !RANGES_BROKEN_CPO_LOOKUP
650             // Optionally support hooking iter_move when the cursor sports a
651             // move() member function.
652             template
653             CONCEPT_REQUIRES_(Same() && detail::InputCursor())>
654             RANGES_CXX14_CONSTEXPR
655             friend auto iter_move(basic_iterator const &it)
656             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
657             (
658             range_access::move(static_cast const &>(it).pos())
659             )
660             #endif
661             };
662              
663             #if RANGES_BROKEN_CPO_LOOKUP
664             namespace _basic_iterator_
665             {
666             // Optionally support hooking iter_move when the cursor sports a
667             // move() member function.
668             template
669             CONCEPT_REQUIRES_(detail::InputCursor())>
670             RANGES_CXX14_CONSTEXPR
671             auto iter_move(basic_iterator const &it)
672             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
673             (
674             range_access::move(range_access::pos(it))
675             )
676             }
677             #endif
678              
679             /// Get a cursor from a basic_iterator
680             struct get_cursor_fn
681             {
682             template
683             RANGES_CXX14_CONSTEXPR
684             Cur &operator()(basic_iterator &it) const noexcept
685             {
686             return range_access::pos(it);
687             }
688             template
689             RANGES_CXX14_CONSTEXPR
690             Cur const &operator()(basic_iterator const &it) const noexcept
691             {
692             return range_access::pos(it);
693             }
694             template
695             RANGES_CXX14_CONSTEXPR
696             Cur operator()(basic_iterator && it) const
697             noexcept(std::is_nothrow_move_constructible::value)
698             {
699             return range_access::pos(std::move(it));
700             }
701             };
702              
703             /// \sa `get_cursor_fn`
704             /// \ingroup group-utility
705             RANGES_INLINE_VARIABLE(get_cursor_fn, get_cursor)
706             /// @}
707             }
708             }
709              
710             /// \cond
711             namespace ranges
712             {
713             inline namespace v3
714             {
715             // common_reference specializations for basic_proxy_reference
716             template
717             struct basic_common_reference, U, TQual, UQual>
718             : basic_common_reference, U, TQual, UQual>
719             {};
720             template
721             struct basic_common_reference, TQual, UQual>
722             : basic_common_reference, TQual, UQual>
723             {};
724             template
725             struct basic_common_reference, detail::basic_proxy_reference, TQual, UQual>
726             : basic_common_reference, detail::cursor_reference_t, TQual, UQual>
727             {};
728              
729             // common_type specializations for basic_proxy_reference
730             template
731             struct common_type, U>
732             : common_type, U>
733             {};
734             template
735             struct common_type>
736             : common_type>
737             {};
738             template
739             struct common_type, detail::basic_proxy_reference>
740             : common_type, range_access::cursor_value_t>
741             {};
742             }
743             }
744              
745             namespace ranges
746             {
747             inline namespace v3
748             {
749             /// \cond
750             namespace detail
751             {
752             template()>
753             struct std_iterator_traits
754             {
755             using iterator_category = std::output_iterator_tag;
756             using difference_type = typename iterator_associated_types_base::difference_type;
757             using value_type = void;
758             using reference = void;
759             using pointer = void;
760             };
761              
762             template
763             struct std_iterator_traits
764             : iterator_associated_types_base
765             {
766             using iterator_category =
767             ::meta::_t<
768             downgrade_iterator_category<
769             typename std_iterator_traits::iterator_category,
770             typename std_iterator_traits::reference>>;
771             };
772             }
773             /// \endcond
774             }
775             }
776              
777             namespace std
778             {
779             template
780             struct iterator_traits< ::ranges::basic_iterator>
781             : ::ranges::detail::std_iterator_traits
782             {};
783             }
784             /// \endcond
785              
786             #endif