aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/iterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/iterator.h')
-rw-r--r--include/EASTL/iterator.h1192
1 files changed, 1192 insertions, 0 deletions
diff --git a/include/EASTL/iterator.h b/include/EASTL/iterator.h
new file mode 100644
index 0000000..d2dc899
--- /dev/null
+++ b/include/EASTL/iterator.h
@@ -0,0 +1,1192 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_ITERATOR_H
+#define EASTL_ITERATOR_H
+
+
+#include <EASTL/internal/config.h>
+#include <EASTL/internal/move_help.h>
+#include <EASTL/initializer_list.h>
+
+EA_DISABLE_ALL_VC_WARNINGS();
+
+#include <stddef.h>
+
+EA_RESTORE_ALL_VC_WARNINGS();
+
+// If the user has specified that we use std iterator
+// categories instead of EASTL iterator categories,
+// then #include <iterator>.
+#if EASTL_STD_ITERATOR_CATEGORY_ENABLED
+ EA_DISABLE_ALL_VC_WARNINGS();
+
+ #include <iterator>
+
+ EA_RESTORE_ALL_VC_WARNINGS();
+#endif
+
+
+EA_DISABLE_VC_WARNING(4619); // There is no warning number 'number'.
+EA_DISABLE_VC_WARNING(4217); // Member template functions cannot be used for copy-assignment or copy-construction.
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
+#endif
+
+
+
+namespace eastl
+{
+ /// iterator_status_flag
+ ///
+ /// Defines the validity status of an iterator. This is primarily used for
+ /// iterator validation in debug builds. These are implemented as OR-able
+ /// flags (as opposed to mutually exclusive values) in order to deal with
+ /// the nature of iterator status. In particular, an iterator may be valid
+ /// but not dereferencable, as in the case with an iterator to container end().
+ /// An iterator may be valid but also dereferencable, as in the case with an
+ /// iterator to container begin().
+ ///
+ enum iterator_status_flag
+ {
+ isf_none = 0x00, /// This is called none and not called invalid because it is not strictly the opposite of invalid.
+ isf_valid = 0x01, /// The iterator is valid, which means it is in the range of [begin, end].
+ isf_current = 0x02, /// The iterator is valid and points to the same element it did when created. For example, if an iterator points to vector::begin() but an element is inserted at the front, the iterator is valid but not current. Modification of elements in place do not make iterators non-current.
+ isf_can_dereference = 0x04 /// The iterator is dereferencable, which means it is in the range of [begin, end). It may or may not be current.
+ };
+
+
+
+ // The following declarations are taken directly from the C++ standard document.
+ // input_iterator_tag, etc.
+ // iterator
+ // iterator_traits
+ // reverse_iterator
+
+ // Iterator categories
+ // Every iterator is defined as belonging to one of the iterator categories that
+ // we define here. These categories come directly from the C++ standard.
+ #if !EASTL_STD_ITERATOR_CATEGORY_ENABLED // If we are to use our own iterator category definitions...
+ struct input_iterator_tag { };
+ struct output_iterator_tag { };
+ struct forward_iterator_tag : public input_iterator_tag { };
+ struct bidirectional_iterator_tag : public forward_iterator_tag { };
+ struct random_access_iterator_tag : public bidirectional_iterator_tag { };
+ struct contiguous_iterator_tag : public random_access_iterator_tag { }; // Extension to the C++ standard. Contiguous ranges are more than random access, they are physically contiguous.
+ #endif
+
+
+ // struct iterator
+ template <typename Category, typename T, typename Distance = ptrdiff_t,
+ typename Pointer = T*, typename Reference = T&>
+ struct iterator
+ {
+ typedef Category iterator_category;
+ typedef T value_type;
+ typedef Distance difference_type;
+ typedef Pointer pointer;
+ typedef Reference reference;
+ };
+
+
+ // struct iterator_traits
+ template <typename Iterator>
+ struct iterator_traits
+ {
+ typedef typename Iterator::iterator_category iterator_category;
+ typedef typename Iterator::value_type value_type;
+ typedef typename Iterator::difference_type difference_type;
+ typedef typename Iterator::pointer pointer;
+ typedef typename Iterator::reference reference;
+ };
+
+ template <typename T>
+ struct iterator_traits<T*>
+ {
+ typedef EASTL_ITC_NS::random_access_iterator_tag iterator_category; // To consider: Change this to contiguous_iterator_tag for the case that
+ typedef T value_type; // EASTL_ITC_NS is "eastl" instead of "std".
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+ };
+
+ template <typename T>
+ struct iterator_traits<const T*>
+ {
+ typedef EASTL_ITC_NS::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ typedef const T* pointer;
+ typedef const T& reference;
+ };
+
+
+
+
+ /// is_iterator_wrapper
+ ///
+ /// Tells if an Iterator type is a wrapper type as opposed to a regular type.
+ /// Relies on the class declaring a typedef called wrapped_iterator_type.
+ ///
+ /// Examples of wrapping iterators:
+ /// reverse_iterator
+ /// generic_iterator
+ /// move_iterator
+ /// Examples of non-wrapping iterators:
+ /// iterator
+ /// list::iterator
+ /// char*
+ ///
+ /// Example behavior:
+ /// is_iterator_wrapper(int*)::value => false
+ /// is_iterator_wrapper(eastl::array<char>*)::value => false
+ /// is_iterator_wrapper(eastl::vector<int>::iterator)::value => false
+ /// is_iterator_wrapper(eastl::generic_iterator<int*>)::value => true
+ /// is_iterator_wrapper(eastl::move_iterator<eastl::array<int>::iterator>)::value => true
+ ///
+ template<typename Iterator>
+ class is_iterator_wrapper
+ {
+ template<typename>
+ static eastl::no_type test(...);
+
+ template<typename U>
+ static eastl::yes_type test(typename U::wrapped_iterator_type*, typename eastl::enable_if<eastl::is_class<U>::value>::type* = 0);
+
+ public:
+ EA_DISABLE_VC_WARNING(6334)
+ static const bool value = (sizeof(test<Iterator>(NULL)) == sizeof(eastl::yes_type));
+ EA_RESTORE_VC_WARNING()
+ };
+
+
+ /// unwrap_iterator
+ ///
+ /// Takes a wrapper Iterator (e.g. move_iterator, reverse_iterator, generic_iterator) instance
+ /// and returns the wrapped iterator type. If Iterator is not a wrapper (including being a pointer),
+ /// or is not an iterator, then this function returns it as-is.
+ /// unwrap_iterator unwraps only a single layer of iterator at a time. You need to call it twice,
+ /// for example, to unwrap two layers of iterators.
+ ///
+ /// Example usage:
+ /// int* pInt = unwrap_iterator(&pIntArray[15]);
+ /// int* pInt = unwrap_iterator(generic_iterator(&pIntArray[15]));
+ /// MyVector::iterator it = unwrap_iterator(myVector.begin());
+ /// MyVector::iterator it = unwrap_iterator(move_iterator(myVector.begin()));
+ ///
+ template <typename Iterator, bool isWrapper>
+ struct is_iterator_wrapper_helper
+ {
+ typedef Iterator iterator_type;
+
+ static iterator_type get_base(Iterator it)
+ { return it; }
+ };
+
+
+ template <typename Iterator>
+ struct is_iterator_wrapper_helper<Iterator, true>
+ {
+ typedef typename Iterator::iterator_type iterator_type;
+
+ static iterator_type get_base(Iterator it)
+ { return it.base(); }
+ };
+
+ template <typename Iterator>
+ inline typename is_iterator_wrapper_helper<Iterator, eastl::is_iterator_wrapper<Iterator>::value>::iterator_type unwrap_iterator(Iterator it)
+ { return eastl::is_iterator_wrapper_helper<Iterator, eastl::is_iterator_wrapper<Iterator>::value>::get_base(it); }
+
+
+
+ /// reverse_iterator
+ ///
+ /// From the C++ standard:
+ /// Bidirectional and random access iterators have corresponding reverse
+ /// iterator adaptors that iterate through the data structure in the
+ /// opposite direction. They have the same signatures as the corresponding
+ /// iterators. The fundamental relation between a reverse iterator and its
+ /// corresponding iterator i is established by the identity:
+ /// &*(reverse_iterator(i)) == &*(i - 1).
+ /// This mapping is dictated by the fact that while there is always a pointer
+ /// past the end of an array, there might not be a valid pointer before the
+ /// beginning of an array.
+ ///
+ template <typename Iterator>
+ class reverse_iterator : public iterator<typename eastl::iterator_traits<Iterator>::iterator_category,
+ typename eastl::iterator_traits<Iterator>::value_type,
+ typename eastl::iterator_traits<Iterator>::difference_type,
+ typename eastl::iterator_traits<Iterator>::pointer,
+ typename eastl::iterator_traits<Iterator>::reference>
+ {
+ public:
+ typedef Iterator iterator_type;
+ typedef iterator_type wrapped_iterator_type; // This is not in the C++ Standard; it's used by use to identify it as a wrapping iterator type.
+ typedef typename eastl::iterator_traits<Iterator>::pointer pointer;
+ typedef typename eastl::iterator_traits<Iterator>::reference reference;
+ typedef typename eastl::iterator_traits<Iterator>::difference_type difference_type;
+
+ protected:
+ Iterator mIterator;
+
+ public:
+ EA_CPP14_CONSTEXPR reverse_iterator() // It's important that we construct mIterator, because if Iterator
+ : mIterator() { } // is a pointer, there's a difference between doing it and not.
+
+ EA_CPP14_CONSTEXPR explicit reverse_iterator(iterator_type i)
+ : mIterator(i) { }
+
+ EA_CPP14_CONSTEXPR reverse_iterator(const reverse_iterator& ri)
+ : mIterator(ri.mIterator) { }
+
+ template <typename U>
+ EA_CPP14_CONSTEXPR reverse_iterator(const reverse_iterator<U>& ri)
+ : mIterator(ri.base()) { }
+
+ // This operator= isn't in the standard, but the the C++
+ // library working group has tentatively approved it, as it
+ // allows const and non-const reverse_iterators to interoperate.
+ template <typename U>
+ EA_CPP14_CONSTEXPR reverse_iterator<Iterator>& operator=(const reverse_iterator<U>& ri)
+ { mIterator = ri.base(); return *this; }
+
+ EA_CPP14_CONSTEXPR iterator_type base() const
+ { return mIterator; }
+
+ EA_CPP14_CONSTEXPR reference operator*() const
+ {
+ iterator_type i(mIterator);
+ return *--i;
+ }
+
+ EA_CPP14_CONSTEXPR pointer operator->() const
+ { return &(operator*()); }
+
+ EA_CPP14_CONSTEXPR reverse_iterator& operator++()
+ { --mIterator; return *this; }
+
+ EA_CPP14_CONSTEXPR reverse_iterator operator++(int)
+ {
+ reverse_iterator ri(*this);
+ --mIterator;
+ return ri;
+ }
+
+ EA_CPP14_CONSTEXPR reverse_iterator& operator--()
+ { ++mIterator; return *this; }
+
+ EA_CPP14_CONSTEXPR reverse_iterator operator--(int)
+ {
+ reverse_iterator ri(*this);
+ ++mIterator;
+ return ri;
+ }
+
+ EA_CPP14_CONSTEXPR reverse_iterator operator+(difference_type n) const
+ { return reverse_iterator(mIterator - n); }
+
+ EA_CPP14_CONSTEXPR reverse_iterator& operator+=(difference_type n)
+ { mIterator -= n; return *this; }
+
+ EA_CPP14_CONSTEXPR reverse_iterator operator-(difference_type n) const
+ { return reverse_iterator(mIterator + n); }
+
+ EA_CPP14_CONSTEXPR reverse_iterator& operator-=(difference_type n)
+ { mIterator += n; return *this; }
+
+ // http://cplusplus.github.io/LWG/lwg-defects.html#386,
+ // http://llvm.org/bugs/show_bug.cgi?id=17883
+ // random_access_iterator operator[] is merely required to return something convertible to reference.
+ // reverse_iterator operator[] can't necessarily know what to return as the underlying iterator
+ // operator[] may return something other than reference.
+ EA_CPP14_CONSTEXPR reference operator[](difference_type n) const
+ { return mIterator[-n - 1]; }
+ };
+
+
+ // The C++ library working group has tentatively approved the usage of two
+ // template parameters (Iterator1 and Iterator2) in order to allow reverse_iterators
+ // and const_reverse iterators to be comparable. This is a similar issue to the
+ // C++ defect report #179 regarding comparison of container iterators and const_iterators.
+ //
+ // libstdc++ reports that std::relops breaks the usage of two iterator types and if we
+ // want to support relops then we need to also make versions of each of below with
+ // a single template parameter to placate std::relops. But relops is hardly used due to
+ // the troubles it causes and so we are avoiding support here until somebody complains about it.
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator==(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() == b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator<(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() > b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator!=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() != b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator>(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() < b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator<=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() >= b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline bool
+ operator>=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return a.base() <= b.base(); }
+
+
+ template <typename Iterator1, typename Iterator2>
+ EA_CPP14_CONSTEXPR inline typename reverse_iterator<Iterator1>::difference_type
+ operator-(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)
+ { return b.base() - a.base(); }
+
+
+ template <typename Iterator>
+ EA_CPP14_CONSTEXPR inline reverse_iterator<Iterator>
+ operator+(typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& a)
+ { return reverse_iterator<Iterator>(a.base() - n); }
+
+
+ /// is_reverse_iterator
+ ///
+ /// This is a type traits extension utility.
+ /// Given an iterator, tells if it's a reverse_iterator vs anything else.
+ /// If it's a reverse iterator wrapped by another iterator then value is false.
+ /// To consider: Detect that if it's a move_iterator<reverse_iterator> and unwrap
+ /// move_iterator so we can detect that underneath it's reverse_iterator.
+ ///
+ template <typename T>
+ struct is_reverse_iterator
+ : public eastl::false_type {};
+
+ template<typename Iterator>
+ struct is_reverse_iterator< eastl::reverse_iterator<Iterator> >
+ : public eastl::true_type {};
+
+
+
+ /// unwrap_reverse_iterator
+ ///
+ /// Returns Iterator::get_base() if it's a reverse_iterator, else returns Iterator as-is.
+ ///
+ /// Example usage:
+ /// vector<int> intVector;
+ /// eastl::reverse_iterator<vector<int>::iterator> reverseIterator(intVector.begin());
+ /// vector<int>::iterator it = unwrap_reverse_iterator(reverseIterator);
+ ///
+ /// Disabled until there is considered a good use for it.
+ /// template <typename Iterator>
+ /// inline typename eastl::is_iterator_wrapper_helper<Iterator, eastl::is_reverse_iterator<Iterator>::value>::iterator_type unwrap_reverse_iterator(Iterator it)
+ /// { return eastl::is_iterator_wrapper_helper<Iterator, eastl::is_reverse_iterator<Iterator>::value>::get_base(it); }
+
+
+
+ /// move_iterator
+ ///
+ /// From the C++11 Standard, section 24.5.3.1:
+ /// Class template move_iterator is an iterator adaptor with the same behavior as the underlying iterator
+ /// except that its dereference operator implicitly converts the value returned by the underlying iterator's
+ /// dereference operator to an rvalue reference. Some generic algorithms can be called with move iterators to
+ /// replace copying with moving.
+
+ template<typename Iterator>
+ class move_iterator // Don't inherit from iterator.
+ {
+ public:
+ typedef Iterator iterator_type;
+ typedef iterator_type wrapped_iterator_type; // This is not in the C++ Standard; it's used by use to identify it as a wrapping iterator type.
+ typedef iterator_traits<Iterator> traits_type;
+ typedef typename traits_type::iterator_category iterator_category;
+ typedef typename traits_type::value_type value_type;
+ typedef typename traits_type::difference_type difference_type;
+ typedef Iterator pointer;
+ typedef value_type&& reference;
+
+ protected:
+ iterator_type mIterator;
+
+ public:
+ move_iterator()
+ : mIterator()
+ {
+ }
+
+ explicit move_iterator(iterator_type mi)
+ : mIterator(mi) { }
+
+ template<typename U>
+ move_iterator(const move_iterator<U>& mi)
+ : mIterator(mi.base())
+ {
+ }
+
+ iterator_type base() const
+ { return mIterator; }
+
+ reference operator*() const
+ { return eastl::move(*mIterator); }
+
+ pointer operator->() const
+ { return mIterator; }
+
+ move_iterator& operator++()
+ {
+ ++mIterator;
+ return *this;
+ }
+
+ move_iterator operator++(int)
+ {
+ move_iterator tempMoveIterator = *this;
+ ++mIterator;
+ return tempMoveIterator;
+ }
+
+ move_iterator& operator--()
+ {
+ --mIterator;
+ return *this;
+ }
+
+ move_iterator operator--(int)
+ {
+ move_iterator tempMoveIterator = *this;
+ --mIterator;
+ return tempMoveIterator;
+ }
+
+ move_iterator operator+(difference_type n) const
+ { return move_iterator(mIterator + n); }
+
+ move_iterator& operator+=(difference_type n)
+ {
+ mIterator += n;
+ return *this;
+ }
+
+ move_iterator operator-(difference_type n) const
+ { return move_iterator(mIterator - n); }
+
+ move_iterator& operator-=(difference_type n)
+ {
+ mIterator -= n;
+ return *this;
+ }
+
+ reference operator[](difference_type n) const
+ { return eastl::move(mIterator[n]); }
+ };
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator==(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return a.base() == b.base(); }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator!=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return !(a == b); }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator<(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return a.base() < b.base(); }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator<=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return !(b < a); }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator>(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return b < a; }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline bool
+ operator>=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)
+ { return !(a < b); }
+
+
+ template<typename Iterator1, typename Iterator2>
+ inline auto
+ operator-(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b) -> decltype(a.base() - b.base())
+ { return a.base() - b.base(); }
+
+
+ template<typename Iterator>
+ inline move_iterator<Iterator>
+ operator+(typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& a)
+ { return a + n; }
+
+
+ template<typename Iterator>
+ inline move_iterator<Iterator> make_move_iterator(Iterator i)
+ { return move_iterator<Iterator>(i); }
+
+
+ // make_move_if_noexcept_iterator returns move_iterator<Iterator> if the Iterator is of a noexcept type;
+ // otherwise returns Iterator as-is. The point of this is to be able to avoid moves that can generate exceptions and instead
+ // fall back to copies or whatever the default IteratorType::operator* returns for use by copy/move algorithms.
+ // To consider: merge the conditional expression usage here with the one used by move_if_noexcept, as they are the same condition.
+ #if EASTL_EXCEPTIONS_ENABLED
+ template <typename Iterator, typename IteratorType = typename eastl::conditional<eastl::is_nothrow_move_constructible<typename eastl::iterator_traits<Iterator>::value_type>::value ||
+ !eastl::is_copy_constructible<typename eastl::iterator_traits<Iterator>::value_type>::value,
+ eastl::move_iterator<Iterator>, Iterator>::type>
+ inline IteratorType make_move_if_noexcept_iterator(Iterator i)
+ { return IteratorType(i); }
+ #else
+ // Else there are no exceptions and thus we always return a move_iterator.
+ template <typename Iterator>
+ inline eastl::move_iterator<Iterator> make_move_if_noexcept_iterator(Iterator i)
+ { return eastl::move_iterator<Iterator>(i); }
+ #endif
+
+
+
+ /// is_move_iterator
+ ///
+ /// This is a type traits extension utility.
+ /// Given an iterator, tells if it's a move iterator vs anything else.
+ /// Example usage (though somewhat useless):
+ /// template <typename T>
+ /// bool IsMoveIterator() { return typename eastl::is_move_iterator<T>::value; }
+ ///
+ template <typename T>
+ struct is_move_iterator
+ : public eastl::false_type {};
+
+ template<typename Iterator>
+ struct is_move_iterator< eastl::move_iterator<Iterator> >
+ : public eastl::true_type {};
+
+
+ /// unwrap_move_iterator
+ ///
+ /// Returns Iterator::get_base() if it's a move_iterator, else returns Iterator as-is.
+ ///
+ /// Example usage:
+ /// vector<int> intVector;
+ /// eastl::move_iterator<vector<int>::iterator> moveIterator(intVector.begin());
+ /// vector<int>::iterator it = unwrap_move_iterator(moveIterator);
+ ///
+ template <typename Iterator>
+ inline typename eastl::is_iterator_wrapper_helper<Iterator, eastl::is_move_iterator<Iterator>::value>::iterator_type unwrap_move_iterator(Iterator it)
+ { return eastl::is_iterator_wrapper_helper<Iterator, eastl::is_move_iterator<Iterator>::value>::get_base(it); }
+
+
+
+
+ /// back_insert_iterator
+ ///
+ /// A back_insert_iterator is simply a class that acts like an iterator but when you
+ /// assign a value to it, it calls push_back on the container with the value.
+ ///
+ template <typename Container>
+ class back_insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
+ {
+ public:
+ typedef back_insert_iterator<Container> this_type;
+ typedef Container container_type;
+ typedef typename Container::const_reference const_reference;
+
+ protected:
+ Container& container;
+
+ public:
+ //back_insert_iterator(); // Not valid. Must construct with a Container.
+
+ //back_insert_iterator(const this_type& x) // Compiler-implemented
+ // : container(x.container) { }
+
+ explicit back_insert_iterator(Container& x)
+ : container(x) { }
+
+ back_insert_iterator& operator=(const_reference value)
+ { container.push_back(value); return *this; }
+
+ back_insert_iterator& operator=(typename Container::value_type&& value)
+ { container.push_back(eastl::move(value)); return *this; }
+
+ back_insert_iterator& operator*()
+ { return *this; }
+
+ back_insert_iterator& operator++()
+ { return *this; } // This is by design.
+
+ back_insert_iterator operator++(int)
+ { return *this; } // This is by design.
+
+ protected:
+ void operator=(const this_type&){} // Declared to avoid compiler warnings about inability to generate this function.
+ };
+
+
+ /// back_inserter
+ ///
+ /// Creates an instance of a back_insert_iterator.
+ ///
+ template <typename Container>
+ inline back_insert_iterator<Container>
+ back_inserter(Container& x)
+ { return back_insert_iterator<Container>(x); }
+
+
+
+
+ /// front_insert_iterator
+ ///
+ /// A front_insert_iterator is simply a class that acts like an iterator but when you
+ /// assign a value to it, it calls push_front on the container with the value.
+ ///
+ template <typename Container>
+ class front_insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
+ {
+ public:
+ typedef front_insert_iterator<Container> this_type;
+ typedef Container container_type;
+ typedef typename Container::const_reference const_reference;
+
+ protected:
+ Container& container;
+
+ public:
+ //front_insert_iterator(); // Not valid. Must construct with a Container.
+
+ //front_insert_iterator(const this_type& x) // Compiler-implemented
+ // : container(x.container) { }
+
+ explicit front_insert_iterator(Container& x)
+ : container(x) { }
+
+ front_insert_iterator& operator=(const_reference value)
+ { container.push_front(value); return *this; }
+
+ front_insert_iterator& operator*()
+ { return *this; }
+
+ front_insert_iterator& operator++()
+ { return *this; } // This is by design.
+
+ front_insert_iterator operator++(int)
+ { return *this; } // This is by design.
+
+ protected:
+ void operator=(const this_type&){} // Declared to avoid compiler warnings about inability to generate this function.
+ };
+
+
+ /// front_inserter
+ ///
+ /// Creates an instance of a front_insert_iterator.
+ ///
+ template <typename Container>
+ inline front_insert_iterator<Container>
+ front_inserter(Container& x)
+ { return front_insert_iterator<Container>(x); }
+
+
+
+
+ /// insert_iterator
+ ///
+ /// An insert_iterator is like an iterator except that when you assign a value to it,
+ /// the insert_iterator inserts the value into the container and increments the iterator.
+ ///
+ /// insert_iterator is an iterator adaptor that functions as an OutputIterator:
+ /// assignment through an insert_iterator inserts an object into a container.
+ /// Specifically, if ii is an insert_iterator, then ii keeps track of a container c and
+ /// an insertion point p; the expression *ii = x performs the insertion container.insert(p, x).
+ ///
+ /// If you assign through an insert_iterator several times, then you will be inserting
+ /// several elements into the underlying container. In the case of a sequence, they will
+ /// appear at a particular location in the underlying sequence, in the order in which
+ /// they were inserted: one of the arguments to insert_iterator's constructor is an
+ /// iterator p, and the new range will be inserted immediately before p.
+ ///
+ template <typename Container>
+ class insert_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
+ {
+ public:
+ typedef Container container_type;
+ typedef typename Container::iterator iterator_type;
+ typedef typename Container::const_reference const_reference;
+
+ protected:
+ Container& container;
+ iterator_type it;
+
+ public:
+ // This assignment operator is defined more to stop compiler warnings (e.g. VC++ C4512)
+ // than to be useful. However, it does allow an insert_iterator to be assigned to another
+ // insert iterator provided that they point to the same container.
+ insert_iterator& operator=(const insert_iterator& x)
+ {
+ EASTL_ASSERT(&x.container == &container);
+ it = x.it;
+ return *this;
+ }
+
+ insert_iterator(Container& x, iterator_type itNew)
+ : container(x), it(itNew) {}
+
+ insert_iterator& operator=(const_reference value)
+ {
+ it = container.insert(it, value);
+ ++it;
+ return *this;
+ }
+
+ insert_iterator& operator*()
+ { return *this; }
+
+ insert_iterator& operator++()
+ { return *this; } // This is by design.
+
+ insert_iterator& operator++(int)
+ { return *this; } // This is by design.
+
+ }; // insert_iterator
+
+
+ /// inserter
+ ///
+ /// Creates an instance of an insert_iterator.
+ ///
+ template <typename Container, typename Iterator>
+ inline eastl::insert_iterator<Container>
+ inserter(Container& x, Iterator i)
+ {
+ typedef typename Container::iterator iterator;
+ return eastl::insert_iterator<Container>(x, iterator(i));
+ }
+
+
+ /// is_insert_iterator
+ ///
+ /// This is a type traits extension utility.
+ /// Given an iterator, tells if it's an insert_iterator vs anything else.
+ /// If it's a insert_iterator wrapped by another iterator then value is false.
+ ///
+ template <typename T>
+ struct is_insert_iterator
+ : public eastl::false_type {};
+
+ template<typename Iterator>
+ struct is_insert_iterator< eastl::insert_iterator<Iterator> >
+ : public eastl::true_type {};
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ /// distance
+ ///
+ /// Implements the distance() function. There are two versions, one for
+ /// random access iterators (e.g. with vector) and one for regular input
+ /// iterators (e.g. with list). The former is more efficient.
+ ///
+ template <typename InputIterator>
+ EA_CONSTEXPR
+ inline typename eastl::iterator_traits<InputIterator>::difference_type
+ distance_impl(InputIterator first, InputIterator last, EASTL_ITC_NS::input_iterator_tag)
+ {
+ typename eastl::iterator_traits<InputIterator>::difference_type n = 0;
+
+ while(first != last)
+ {
+ ++first;
+ ++n;
+ }
+ return n;
+ }
+
+ template <typename RandomAccessIterator>
+ EA_CONSTEXPR
+ inline typename eastl::iterator_traits<RandomAccessIterator>::difference_type
+ distance_impl(RandomAccessIterator first, RandomAccessIterator last, EASTL_ITC_NS::random_access_iterator_tag)
+ {
+ return last - first;
+ }
+
+ // Special version defined so that std C++ iterators can be recognized by
+ // this function. Unfortunately, this function treats all foreign iterators
+ // as InputIterators and thus can seriously hamper performance in the case
+ // of large ranges of bidirectional_iterator_tag iterators.
+ //template <typename InputIterator>
+ //inline typename eastl::iterator_traits<InputIterator>::difference_type
+ //distance_impl(InputIterator first, InputIterator last, ...)
+ //{
+ // typename eastl::iterator_traits<InputIterator>::difference_type n = 0;
+ //
+ // while(first != last)
+ // {
+ // ++first;
+ // ++n;
+ // }
+ // return n;
+ //}
+
+ template <typename InputIterator>
+ EA_CONSTEXPR
+ inline typename eastl::iterator_traits<InputIterator>::difference_type
+ distance(InputIterator first, InputIterator last)
+ {
+ typedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;
+
+ return eastl::distance_impl(first, last, IC());
+ }
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ /// advance
+ ///
+ /// Implements the advance() function. There are three versions, one for
+ /// random access iterators (e.g. with vector), one for bidirectional
+ /// iterators (list) and one for regular input iterators (e.g. with slist).
+ ///
+ template <typename InputIterator, typename Distance>
+ inline void
+ advance_impl(InputIterator& i, Distance n, EASTL_ITC_NS::input_iterator_tag)
+ {
+ while(n--)
+ ++i;
+ }
+
+ template <bool signedDistance>
+ struct advance_bi_impl
+ {
+ template <typename BidirectionalIterator, typename Distance>
+ static void advance_impl(BidirectionalIterator& i, Distance n) // Specialization for unsigned distance type.
+ {
+ while(n--)
+ ++i;
+ }
+ };
+
+ template <>
+ struct advance_bi_impl<true>
+ {
+ template <typename BidirectionalIterator, typename Distance>
+ static void advance_impl(BidirectionalIterator& i, Distance n) // Specialization for signed distance type.
+ {
+ if(n > 0)
+ {
+ while(n--)
+ ++i;
+ }
+ else
+ {
+ while(n++)
+ --i;
+ }
+ }
+ };
+
+ template <typename BidirectionalIterator, typename Distance>
+ inline void
+ advance_impl(BidirectionalIterator& i, Distance n, EASTL_ITC_NS::bidirectional_iterator_tag)
+ {
+ advance_bi_impl<eastl::is_signed<Distance>::value>::advance_impl(i, n);
+ }
+
+ template <typename RandomAccessIterator, typename Distance>
+ inline void
+ advance_impl(RandomAccessIterator& i, Distance n, EASTL_ITC_NS::random_access_iterator_tag)
+ {
+ i += n;
+ }
+
+ // Special version defined so that std C++ iterators can be recognized by
+ // this function. Unfortunately, this function treats all foreign iterators
+ // as InputIterators and thus can seriously hamper performance in the case
+ // of large ranges of bidirectional_iterator_tag iterators.
+ //template <typename InputIterator, typename Distance>
+ //inline void
+ //advance_impl(InputIterator& i, Distance n, ...)
+ //{
+ // while(n--)
+ // ++i;
+ //}
+
+ template <typename InputIterator, typename Distance>
+ inline void
+ advance(InputIterator& i, Distance n)
+ {
+ typedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;
+
+ eastl::advance_impl(i, n, IC());
+ }
+
+
+ // eastl::next / eastl::prev
+ // Return the nth/-nth successor of iterator it.
+ //
+ // http://en.cppreference.com/w/cpp/iterator/next
+ //
+ template<typename InputIterator>
+ inline InputIterator
+ next(InputIterator it, typename eastl::iterator_traits<InputIterator>::difference_type n = 1)
+ {
+ eastl::advance(it, n);
+ return it;
+ }
+
+ template<typename InputIterator>
+ inline InputIterator
+ prev(InputIterator it, typename eastl::iterator_traits<InputIterator>::difference_type n = 1)
+ {
+ eastl::advance(it, -n);
+ return it;
+ }
+
+
+#if defined(EA_COMPILER_CPP11_ENABLED) && EA_COMPILER_CPP11_ENABLED
+
+ // eastl::data
+ //
+ // http://en.cppreference.com/w/cpp/iterator/data
+ //
+ template <class Container>
+ EA_CPP14_CONSTEXPR auto data(Container& c) -> decltype(c.data())
+ { return c.data(); }
+
+ template <class Container>
+ EA_CPP14_CONSTEXPR auto data(const Container& c) -> decltype(c.data())
+ { return c.data(); }
+
+ template <class T, size_t N>
+ EA_CPP14_CONSTEXPR T* data(T(&array)[N]) EA_NOEXCEPT
+ { return array; }
+
+ template <class E>
+ EA_CPP14_CONSTEXPR const E* data(std::initializer_list<E> il) EA_NOEXCEPT
+ { return il.begin(); }
+
+
+ // eastl::size
+ //
+ // http://en.cppreference.com/w/cpp/iterator/size
+ //
+ template <class C>
+ EA_CPP14_CONSTEXPR auto size(const C& c) -> decltype(c.size())
+ { return c.size(); }
+
+ template <class T, size_t N>
+ EA_CPP14_CONSTEXPR size_t size(const T (&)[N]) EA_NOEXCEPT
+ { return N; }
+
+
+ // eastl::ssize
+ //
+ // https://en.cppreference.com/w/cpp/iterator/size
+ //
+ template <class T, ptrdiff_t N>
+ EA_CPP14_CONSTEXPR ptrdiff_t ssize(const T(&)[N]) EA_NOEXCEPT
+ { return N; }
+
+ template <class C>
+ EA_CPP14_CONSTEXPR auto ssize(const C& c)
+ -> eastl::common_type_t<ptrdiff_t, eastl::make_signed_t<decltype(c.size())>>
+ {
+ using R = eastl::common_type_t<ptrdiff_t, eastl::make_signed_t<decltype(c.size())>>;
+ return static_cast<R>(c.size());
+ }
+
+
+ // eastl::empty
+ //
+ // http://en.cppreference.com/w/cpp/iterator/empty
+ //
+ template <class Container>
+ EA_CPP14_CONSTEXPR auto empty(const Container& c) -> decltype(c.empty())
+ { return c.empty(); }
+
+ template <class T, size_t N>
+ EA_CPP14_CONSTEXPR bool empty(const T (&)[N]) EA_NOEXCEPT
+ { return false; }
+
+ template <class E>
+ EA_CPP14_CONSTEXPR bool empty(std::initializer_list<E> il) EA_NOEXCEPT
+ { return il.size() == 0; }
+
+#endif // defined(EA_COMPILER_CPP11_ENABLED) && EA_COMPILER_CPP11_ENABLED
+
+
+ // eastl::begin / eastl::end
+ // http://en.cppreference.com/w/cpp/iterator/begin
+ //
+ // In order to enable eastl::begin and eastl::end, the compiler needs to have conforming support
+ // for argument-dependent lookup if it supports C++11 range-based for loops. The reason for this is
+ // that in C++11 range-based for loops result in usage of std::begin/std::end, but allow that to
+ // be overridden by argument-dependent lookup:
+ // C++11 Standard, section 6.5.4, paragraph 1.
+ // "otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively,
+ // where begin and end are looked up with argument-dependent lookup (3.4.2). For the
+ // purposes of this name lookup, namespace std is an associated namespace."
+ // It turns out that one compiler has a problem: GCC 4.6. That version added support for
+ // range-based for loops but has broken argument-dependent lookup which was fixed in GCC 4.7.
+ //
+ #if (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION == 4006))
+ #define EASTL_BEGIN_END_ENABLED 0
+ #else
+ #define EASTL_BEGIN_END_ENABLED 1
+ #endif
+
+ #if EASTL_BEGIN_END_ENABLED
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto begin(Container& container) -> decltype(container.begin())
+ {
+ return container.begin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto begin(const Container& container) -> decltype(container.begin())
+ {
+ return container.begin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto cbegin(const Container& container) -> decltype(container.begin())
+ {
+ return container.begin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto end(Container& container) -> decltype(container.end())
+ {
+ return container.end();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto end(const Container& container) -> decltype(container.end())
+ {
+ return container.end();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto cend(const Container& container) -> decltype(container.end())
+ {
+ return container.end();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto rbegin(Container& container) -> decltype(container.rbegin())
+ {
+ return container.rbegin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto rbegin(const Container& container) -> decltype(container.rbegin())
+ {
+ return container.rbegin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto rend(Container& container) -> decltype(container.rend())
+ {
+ return container.rend();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto rend(const Container& container) -> decltype(container.rend())
+ {
+ return container.rend();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto crbegin(const Container& container) -> decltype(eastl::rbegin(container))
+ {
+ return container.rbegin();
+ }
+
+ template <typename Container>
+ EA_CPP14_CONSTEXPR inline auto crend(const Container& container) -> decltype(eastl::rend(container))
+ {
+ return container.rend();
+ }
+
+ template<typename T, size_t arraySize>
+ EA_CPP14_CONSTEXPR inline T* begin(T (&arrayObject)[arraySize])
+ {
+ return arrayObject;
+ }
+
+ template<typename T, size_t arraySize>
+ EA_CPP14_CONSTEXPR inline T* end(T (&arrayObject)[arraySize])
+ {
+ return (arrayObject + arraySize);
+ }
+
+ template <typename T, size_t arraySize>
+ EA_CPP14_CONSTEXPR inline reverse_iterator<T*> rbegin(T (&arrayObject)[arraySize])
+ {
+ return reverse_iterator<T*>(arrayObject + arraySize);
+ }
+
+ template <typename T, size_t arraySize>
+ EA_CPP14_CONSTEXPR inline reverse_iterator<T*> rend(T (&arrayObject)[arraySize])
+ {
+ return reverse_iterator<T*>(arrayObject);
+ }
+
+ template <typename E>
+ EA_CPP14_CONSTEXPR inline reverse_iterator<const E*> rbegin(std::initializer_list<E> ilist)
+ {
+ return eastl::reverse_iterator<const E*>(ilist.end());
+ }
+
+ template <typename E>
+ EA_CPP14_CONSTEXPR inline reverse_iterator<const E*> rend(std::initializer_list<E> ilist)
+ {
+ return eastl::reverse_iterator<const E*>(ilist.begin());
+ }
+
+ template <typename Iterator>
+ EA_CPP14_CONSTEXPR reverse_iterator<Iterator> make_reverse_iterator(Iterator i)
+ { return reverse_iterator<Iterator>(i); }
+
+ #endif // EASTL_BEGIN_END_ENABLED
+
+} // namespace eastl
+
+
+
+// Some compilers (e.g. GCC 4.6) support range-based for loops, but have a bug with
+// respect to argument-dependent lookup which results on them unilaterally using std::begin/end
+// with range-based for loops. To work around this we #include <iterator> for this case in
+// order to make std::begin/end visible to users of <eastl/iterator.h>, for portability.
+#if !EASTL_BEGIN_END_ENABLED && !defined(EA_COMPILER_NO_RANGE_BASED_FOR_LOOP)
+ #include <iterator>
+#endif
+
+
+
+EA_RESTORE_VC_WARNING();
+EA_RESTORE_VC_WARNING();
+
+#endif // Header include guard