1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2013.
4 // (C) Copyright Gennaro Prota 2003 - 2004.
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 // See http://www.boost.org/libs/container for documentation.
12 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
15 #define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
17 #ifndef BOOST_CONFIG_HPP
18 # include <boost/config.hpp>
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
25 #include <boost/container/detail/config_begin.hpp>
26 #include <boost/container/detail/workaround.hpp>
27 #include <boost/container/allocator_traits.hpp>
28 #include <boost/container/detail/type_traits.hpp>
29 #include <boost/container/detail/value_init.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/move/utility_core.hpp>
32 #include <boost/intrusive/detail/reverse_iterator.hpp>
34 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
35 #include <boost/move/detail/fwd_macros.hpp>
37 #include <boost/container/detail/variadic_templates_tools.hpp>
39 #include <boost/container/detail/iterator.hpp>
44 template <class T, class Difference = std::ptrdiff_t>
45 class constant_iterator
46 : public ::boost::container::iterator
47 <std::random_access_iterator_tag, T, Difference, const T*, const T &>
49 typedef constant_iterator<T, Difference> this_type;
52 explicit constant_iterator(const T &ref, Difference range_size)
53 : m_ptr(&ref), m_num(range_size){}
57 : m_ptr(0), m_num(0){}
59 constant_iterator& operator++()
60 { increment(); return *this; }
62 constant_iterator operator++(int)
64 constant_iterator result (*this);
69 constant_iterator& operator--()
70 { decrement(); return *this; }
72 constant_iterator operator--(int)
74 constant_iterator result (*this);
79 friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
80 { return i.equal(i2); }
82 friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
83 { return !(i == i2); }
85 friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
86 { return i.less(i2); }
88 friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
91 friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
94 friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
97 friend Difference operator- (const constant_iterator& i, const constant_iterator& i2)
98 { return i2.distance_to(i); }
101 constant_iterator& operator+=(Difference off)
102 { this->advance(off); return *this; }
104 constant_iterator operator+(Difference off) const
106 constant_iterator other(*this);
111 friend constant_iterator operator+(Difference off, const constant_iterator& right)
112 { return right + off; }
114 constant_iterator& operator-=(Difference off)
115 { this->advance(-off); return *this; }
117 constant_iterator operator-(Difference off) const
118 { return *this + (-off); }
120 const T& operator*() const
121 { return dereference(); }
123 const T& operator[] (Difference ) const
124 { return dereference(); }
126 const T* operator->() const
127 { return &(dereference()); }
139 bool equal(const this_type &other) const
140 { return m_num == other.m_num; }
142 bool less(const this_type &other) const
143 { return other.m_num < m_num; }
145 const T & dereference() const
148 void advance(Difference n)
151 Difference distance_to(const this_type &other)const
152 { return m_num - other.m_num; }
155 template <class T, class Difference>
156 class value_init_construct_iterator
157 : public ::boost::container::iterator
158 <std::random_access_iterator_tag, T, Difference, const T*, const T &>
160 typedef value_init_construct_iterator<T, Difference> this_type;
163 explicit value_init_construct_iterator(Difference range_size)
164 : m_num(range_size){}
167 value_init_construct_iterator()
170 value_init_construct_iterator& operator++()
171 { increment(); return *this; }
173 value_init_construct_iterator operator++(int)
175 value_init_construct_iterator result (*this);
180 value_init_construct_iterator& operator--()
181 { decrement(); return *this; }
183 value_init_construct_iterator operator--(int)
185 value_init_construct_iterator result (*this);
190 friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
191 { return i.equal(i2); }
193 friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
194 { return !(i == i2); }
196 friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
197 { return i.less(i2); }
199 friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
202 friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
203 { return !(i > i2); }
205 friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
206 { return !(i < i2); }
208 friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
209 { return i2.distance_to(i); }
212 value_init_construct_iterator& operator+=(Difference off)
213 { this->advance(off); return *this; }
215 value_init_construct_iterator operator+(Difference off) const
217 value_init_construct_iterator other(*this);
222 friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
223 { return right + off; }
225 value_init_construct_iterator& operator-=(Difference off)
226 { this->advance(-off); return *this; }
228 value_init_construct_iterator operator-(Difference off) const
229 { return *this + (-off); }
231 //This pseudo-iterator's dereference operations have no sense since value is not
232 //constructed until ::boost::container::construct_in_place is called.
233 //So comment them to catch bad uses
234 //const T& operator*() const;
235 //const T& operator[](difference_type) const;
236 //const T* operator->() const;
247 bool equal(const this_type &other) const
248 { return m_num == other.m_num; }
250 bool less(const this_type &other) const
251 { return other.m_num < m_num; }
253 const T & dereference() const
259 void advance(Difference n)
262 Difference distance_to(const this_type &other)const
263 { return m_num - other.m_num; }
266 template <class T, class Difference>
267 class default_init_construct_iterator
268 : public ::boost::container::iterator
269 <std::random_access_iterator_tag, T, Difference, const T*, const T &>
271 typedef default_init_construct_iterator<T, Difference> this_type;
274 explicit default_init_construct_iterator(Difference range_size)
275 : m_num(range_size){}
278 default_init_construct_iterator()
281 default_init_construct_iterator& operator++()
282 { increment(); return *this; }
284 default_init_construct_iterator operator++(int)
286 default_init_construct_iterator result (*this);
291 default_init_construct_iterator& operator--()
292 { decrement(); return *this; }
294 default_init_construct_iterator operator--(int)
296 default_init_construct_iterator result (*this);
301 friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
302 { return i.equal(i2); }
304 friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
305 { return !(i == i2); }
307 friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
308 { return i.less(i2); }
310 friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
313 friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
314 { return !(i > i2); }
316 friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
317 { return !(i < i2); }
319 friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
320 { return i2.distance_to(i); }
323 default_init_construct_iterator& operator+=(Difference off)
324 { this->advance(off); return *this; }
326 default_init_construct_iterator operator+(Difference off) const
328 default_init_construct_iterator other(*this);
333 friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right)
334 { return right + off; }
336 default_init_construct_iterator& operator-=(Difference off)
337 { this->advance(-off); return *this; }
339 default_init_construct_iterator operator-(Difference off) const
340 { return *this + (-off); }
342 //This pseudo-iterator's dereference operations have no sense since value is not
343 //constructed until ::boost::container::construct_in_place is called.
344 //So comment them to catch bad uses
345 //const T& operator*() const;
346 //const T& operator[](difference_type) const;
347 //const T* operator->() const;
358 bool equal(const this_type &other) const
359 { return m_num == other.m_num; }
361 bool less(const this_type &other) const
362 { return other.m_num < m_num; }
364 const T & dereference() const
370 void advance(Difference n)
373 Difference distance_to(const this_type &other)const
374 { return m_num - other.m_num; }
378 template <class T, class Difference = std::ptrdiff_t>
379 class repeat_iterator
380 : public ::boost::container::iterator
381 <std::random_access_iterator_tag, T, Difference, T*, T&>
383 typedef repeat_iterator<T, Difference> this_type;
385 explicit repeat_iterator(T &ref, Difference range_size)
386 : m_ptr(&ref), m_num(range_size){}
390 : m_ptr(0), m_num(0){}
392 this_type& operator++()
393 { increment(); return *this; }
395 this_type operator++(int)
397 this_type result (*this);
402 this_type& operator--()
403 { increment(); return *this; }
405 this_type operator--(int)
407 this_type result (*this);
412 friend bool operator== (const this_type& i, const this_type& i2)
413 { return i.equal(i2); }
415 friend bool operator!= (const this_type& i, const this_type& i2)
416 { return !(i == i2); }
418 friend bool operator< (const this_type& i, const this_type& i2)
419 { return i.less(i2); }
421 friend bool operator> (const this_type& i, const this_type& i2)
424 friend bool operator<= (const this_type& i, const this_type& i2)
425 { return !(i > i2); }
427 friend bool operator>= (const this_type& i, const this_type& i2)
428 { return !(i < i2); }
430 friend Difference operator- (const this_type& i, const this_type& i2)
431 { return i2.distance_to(i); }
434 this_type& operator+=(Difference off)
435 { this->advance(off); return *this; }
437 this_type operator+(Difference off) const
439 this_type other(*this);
444 friend this_type operator+(Difference off, const this_type& right)
445 { return right + off; }
447 this_type& operator-=(Difference off)
448 { this->advance(-off); return *this; }
450 this_type operator-(Difference off) const
451 { return *this + (-off); }
454 { return dereference(); }
456 T& operator[] (Difference ) const
457 { return dereference(); }
459 T *operator->() const
460 { return &(dereference()); }
472 bool equal(const this_type &other) const
473 { return m_num == other.m_num; }
475 bool less(const this_type &other) const
476 { return other.m_num < m_num; }
478 T & dereference() const
481 void advance(Difference n)
484 Difference distance_to(const this_type &other)const
485 { return m_num - other.m_num; }
488 template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/>
489 class emplace_iterator
490 : public ::boost::container::iterator
491 <std::random_access_iterator_tag, T, Difference, const T*, const T &>
493 typedef emplace_iterator this_type;
496 typedef Difference difference_type;
497 BOOST_CONTAINER_FORCEINLINE explicit emplace_iterator(EmplaceFunctor&e)
498 : m_num(1), m_pe(&e){}
500 BOOST_CONTAINER_FORCEINLINE emplace_iterator()
501 : m_num(0), m_pe(0){}
503 BOOST_CONTAINER_FORCEINLINE this_type& operator++()
504 { increment(); return *this; }
506 this_type operator++(int)
508 this_type result (*this);
513 BOOST_CONTAINER_FORCEINLINE this_type& operator--()
514 { decrement(); return *this; }
516 this_type operator--(int)
518 this_type result (*this);
523 BOOST_CONTAINER_FORCEINLINE friend bool operator== (const this_type& i, const this_type& i2)
524 { return i.equal(i2); }
526 BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const this_type& i, const this_type& i2)
527 { return !(i == i2); }
529 BOOST_CONTAINER_FORCEINLINE friend bool operator< (const this_type& i, const this_type& i2)
530 { return i.less(i2); }
532 BOOST_CONTAINER_FORCEINLINE friend bool operator> (const this_type& i, const this_type& i2)
535 BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const this_type& i, const this_type& i2)
536 { return !(i > i2); }
538 BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const this_type& i, const this_type& i2)
539 { return !(i < i2); }
541 BOOST_CONTAINER_FORCEINLINE friend difference_type operator- (const this_type& i, const this_type& i2)
542 { return i2.distance_to(i); }
545 BOOST_CONTAINER_FORCEINLINE this_type& operator+=(difference_type off)
546 { this->advance(off); return *this; }
548 this_type operator+(difference_type off) const
550 this_type other(*this);
555 BOOST_CONTAINER_FORCEINLINE friend this_type operator+(difference_type off, const this_type& right)
556 { return right + off; }
558 BOOST_CONTAINER_FORCEINLINE this_type& operator-=(difference_type off)
559 { this->advance(-off); return *this; }
561 BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
562 { return *this + (-off); }
565 //This pseudo-iterator's dereference operations have no sense since value is not
566 //constructed until ::boost::container::construct_in_place is called.
567 //So comment them to catch bad uses
568 const T& operator*() const;
569 const T& operator[](difference_type) const;
570 const T* operator->() const;
573 template<class Allocator>
574 void construct_in_place(Allocator &a, T* ptr)
577 template<class DestIt>
578 void assign_in_place(DestIt dest)
582 difference_type m_num;
583 EmplaceFunctor * m_pe;
585 BOOST_CONTAINER_FORCEINLINE void increment()
588 BOOST_CONTAINER_FORCEINLINE void decrement()
591 BOOST_CONTAINER_FORCEINLINE bool equal(const this_type &other) const
592 { return m_num == other.m_num; }
594 BOOST_CONTAINER_FORCEINLINE bool less(const this_type &other) const
595 { return other.m_num < m_num; }
597 BOOST_CONTAINER_FORCEINLINE const T & dereference() const
603 BOOST_CONTAINER_FORCEINLINE void advance(difference_type n)
606 BOOST_CONTAINER_FORCEINLINE difference_type distance_to(const this_type &other)const
607 { return difference_type(m_num - other.m_num); }
610 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
612 template<class ...Args>
613 struct emplace_functor
615 typedef typename container_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
617 emplace_functor(BOOST_FWD_REF(Args)... args)
621 template<class Allocator, class T>
622 BOOST_CONTAINER_FORCEINLINE void operator()(Allocator &a, T *ptr)
623 { emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
625 template<class DestIt>
626 BOOST_CONTAINER_FORCEINLINE void operator()(DestIt dest)
627 { emplace_functor::inplace_impl(dest, index_tuple_t()); }
630 template<class Allocator, class T, std::size_t ...IdxPack>
631 BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
633 allocator_traits<Allocator>::construct
634 (a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
637 template<class DestIt, std::size_t ...IdxPack>
638 BOOST_CONTAINER_FORCEINLINE void inplace_impl(DestIt dest, const container_detail::index_tuple<IdxPack...>&)
640 typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;
641 value_type && tmp= value_type(::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
642 *dest = ::boost::move(tmp);
645 container_detail::tuple<Args&...> args_;
648 template<class ...Args>
649 struct emplace_functor_type
651 typedef emplace_functor<Args...> type;
654 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
656 //Partial specializations cannot match argument list for primary template, so add an extra argument
657 template <BOOST_MOVE_CLASSDFLT9, class Dummy = void>
658 struct emplace_functor_type;
660 #define BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE(N) \
661 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
662 struct emplace_functor##N\
664 explicit emplace_functor##N( BOOST_MOVE_UREF##N )\
665 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
667 template<class Allocator, class T>\
668 void operator()(Allocator &a, T *ptr)\
669 { allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\
671 template<class DestIt>\
672 void operator()(DestIt dest)\
674 typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;\
675 BOOST_MOVE_IF(N, value_type tmp(BOOST_MOVE_MFWD##N), container_detail::value_init<value_type> tmp) ;\
676 *dest = ::boost::move(const_cast<value_type &>(BOOST_MOVE_IF(N, tmp, tmp.get())));\
682 template <BOOST_MOVE_CLASS##N>\
683 struct emplace_functor_type<BOOST_MOVE_TARG##N>\
685 typedef emplace_functor##N BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N type;\
689 BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE)
691 #undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE
695 namespace container_detail {
698 struct has_iterator_category
700 struct two { char _[2]; };
702 template <typename X>
703 static char test(int, typename X::iterator_category*);
705 template <typename X>
706 static two test(int, ...);
708 static const bool value = (1 == sizeof(test<T>(0, 0)));
712 template<class T, bool = has_iterator_category<T>::value >
713 struct is_input_iterator
715 static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
719 struct is_input_iterator<T, false>
721 static const bool value = false;
725 struct is_not_input_iterator
727 static const bool value = !is_input_iterator<T>::value;
730 template<class T, bool = has_iterator_category<T>::value >
731 struct is_forward_iterator
733 static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
737 struct is_forward_iterator<T, false>
739 static const bool value = false;
742 template<class T, bool = has_iterator_category<T>::value >
743 struct is_bidirectional_iterator
745 static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
749 struct is_bidirectional_iterator<T, false>
751 static const bool value = false;
754 template<class IINodeType>
755 struct iiterator_node_value_type {
756 typedef typename IINodeType::value_type type;
759 template<class IIterator>
760 struct iiterator_types
762 typedef typename IIterator::value_type it_value_type;
763 typedef typename iiterator_node_value_type<it_value_type>::type value_type;
764 typedef typename boost::container::iterator_traits<IIterator>::pointer it_pointer;
765 typedef typename boost::container::iterator_traits<IIterator>::difference_type difference_type;
766 typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
767 template rebind_pointer<value_type>::type pointer;
768 typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
769 template rebind_pointer<const value_type>::type const_pointer;
770 typedef typename ::boost::intrusive::
771 pointer_traits<pointer>::reference reference;
772 typedef typename ::boost::intrusive::
773 pointer_traits<const_pointer>::reference const_reference;
774 typedef typename IIterator::iterator_category iterator_category;
777 template<class IIterator, bool IsConst>
778 struct iterator_types
780 typedef typename ::boost::container::iterator
781 < typename iiterator_types<IIterator>::iterator_category
782 , typename iiterator_types<IIterator>::value_type
783 , typename iiterator_types<IIterator>::difference_type
784 , typename iiterator_types<IIterator>::const_pointer
785 , typename iiterator_types<IIterator>::const_reference> type;
788 template<class IIterator>
789 struct iterator_types<IIterator, false>
791 typedef typename ::boost::container::iterator
792 < typename iiterator_types<IIterator>::iterator_category
793 , typename iiterator_types<IIterator>::value_type
794 , typename iiterator_types<IIterator>::difference_type
795 , typename iiterator_types<IIterator>::pointer
796 , typename iiterator_types<IIterator>::reference> type;
799 template<class IIterator, bool IsConst>
800 class iterator_from_iiterator
802 typedef typename iterator_types<IIterator, IsConst>::type types_t;
805 typedef typename types_t::pointer pointer;
806 typedef typename types_t::reference reference;
807 typedef typename types_t::difference_type difference_type;
808 typedef typename types_t::iterator_category iterator_category;
809 typedef typename types_t::value_type value_type;
811 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator()
815 BOOST_CONTAINER_FORCEINLINE explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
819 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
823 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
824 { ++this->m_iit; return *this; }
826 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
828 iterator_from_iiterator result (*this);
833 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
835 //If the iterator_from_iiterator is not a bidirectional iterator, operator-- should not exist
836 BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator_from_iiterator>::value));
837 --this->m_iit; return *this;
840 BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
842 iterator_from_iiterator result (*this);
847 BOOST_CONTAINER_FORCEINLINE friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
848 { return l.m_iit == r.m_iit; }
850 BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
851 { return !(l == r); }
853 BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
854 { return this->m_iit->get_data(); }
856 BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
857 { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
859 BOOST_CONTAINER_FORCEINLINE const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
860 { return this->m_iit; }
866 } //namespace container_detail {
868 using ::boost::intrusive::reverse_iterator;
870 } //namespace container {
871 } //namespace boost {
873 #include <boost/container/detail/config_end.hpp>
875 #endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP