1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2013.
4 // (C) Copyright Gennaro Prota 2003 - 2004.
5 //
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)
9 //
10 // See http://www.boost.org/libs/container for documentation.
11 //
12 //////////////////////////////////////////////////////////////////////////////
13 
14 #ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
15 #define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
16 
17 #ifndef BOOST_CONFIG_HPP
18 #  include <boost/config.hpp>
19 #endif
20 
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #  pragma once
23 #endif
24 
25 #include <boost/container/detail/config_begin.hpp>
26 #include <boost/container/detail/workaround.hpp>
27 #include <boost/container/detail/type_traits.hpp>
28 #include <boost/container/detail/iterator.hpp>
29 
30 namespace boost {
31 namespace container {
32 
33 template <class PseudoReference>
34 struct operator_arrow_proxy
35 {
operator_arrow_proxyboost::container::operator_arrow_proxy36    operator_arrow_proxy(const PseudoReference &px)
37       :  m_value(px)
38    {}
39 
40    typedef PseudoReference element_type;
41 
operator ->boost::container::operator_arrow_proxy42    PseudoReference* operator->() const { return &m_value; }
43 
44    mutable PseudoReference m_value;
45 };
46 
47 template <class T>
48 struct operator_arrow_proxy<T&>
49 {
operator_arrow_proxyboost::container::operator_arrow_proxy50    operator_arrow_proxy(T &px)
51       :  m_value(px)
52    {}
53 
54    typedef T element_type;
55 
operator ->boost::container::operator_arrow_proxy56    T* operator->() const { return const_cast<T*>(&m_value); }
57 
58    T &m_value;
59 };
60 
61 template <class Iterator, class UnaryFunction>
62 class transform_iterator
63    : public UnaryFunction
64    , public boost::container::iterator
65       < typename Iterator::iterator_category
66       , typename dtl::remove_reference<typename UnaryFunction::result_type>::type
67       , typename Iterator::difference_type
68       , operator_arrow_proxy<typename UnaryFunction::result_type>
69       , typename UnaryFunction::result_type>
70 {
71    public:
transform_iterator(const Iterator & it,const UnaryFunction & f=UnaryFunction ())72    explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
73       :  UnaryFunction(f), m_it(it)
74    {}
75 
transform_iterator()76    explicit transform_iterator()
77       :  UnaryFunction(), m_it()
78    {}
79 
80    //Constructors
operator ++()81    transform_iterator& operator++()
82    { increment();   return *this;   }
83 
operator ++(int)84    transform_iterator operator++(int)
85    {
86       transform_iterator result (*this);
87       increment();
88       return result;
89    }
90 
operator ==(const transform_iterator & i,const transform_iterator & i2)91    friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
92    { return i.equal(i2); }
93 
operator !=(const transform_iterator & i,const transform_iterator & i2)94    friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
95    { return !(i == i2); }
96 
97 /*
98    friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
99    { return i2 < i; }
100 
101    friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
102    { return !(i > i2); }
103 
104    friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
105    { return !(i < i2); }
106 */
operator -(const transform_iterator & i,const transform_iterator & i2)107    friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
108    { return i2.distance_to(i); }
109 
110    //Arithmetic
operator +=(typename Iterator::difference_type off)111    transform_iterator& operator+=(typename Iterator::difference_type off)
112    {  this->advance(off); return *this;   }
113 
operator +(typename Iterator::difference_type off) const114    transform_iterator operator+(typename Iterator::difference_type off) const
115    {
116       transform_iterator other(*this);
117       other.advance(off);
118       return other;
119    }
120 
operator +(typename Iterator::difference_type off,const transform_iterator & right)121    friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
122    {  return right + off; }
123 
operator -=(typename Iterator::difference_type off)124    transform_iterator& operator-=(typename Iterator::difference_type off)
125    {  this->advance(-off); return *this;   }
126 
operator -(typename Iterator::difference_type off) const127    transform_iterator operator-(typename Iterator::difference_type off) const
128    {  return *this + (-off);  }
129 
operator *() const130    typename UnaryFunction::result_type operator*() const
131    { return dereference(); }
132 
133    operator_arrow_proxy<typename UnaryFunction::result_type>
operator ->() const134       operator->() const
135    { return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference());  }
136 
base()137    Iterator & base()
138    {  return m_it;   }
139 
base() const140    const Iterator & base() const
141    {  return m_it;   }
142 
143    private:
144    Iterator m_it;
145 
increment()146    void increment()
147    { ++m_it; }
148 
decrement()149    void decrement()
150    { --m_it; }
151 
equal(const transform_iterator & other) const152    bool equal(const transform_iterator &other) const
153    {  return m_it == other.m_it;   }
154 
less(const transform_iterator & other) const155    bool less(const transform_iterator &other) const
156    {  return other.m_it < m_it;   }
157 
dereference() const158    typename UnaryFunction::result_type dereference() const
159    { return UnaryFunction::operator()(*m_it); }
160 
advance(typename Iterator::difference_type n)161    void advance(typename Iterator::difference_type n)
162    {  boost::container::iterator_advance(m_it, n); }
163 
distance_to(const transform_iterator & other) const164    typename Iterator::difference_type distance_to(const transform_iterator &other)const
165    {  return boost::container::iterator_distance(other.m_it, m_it); }
166 };
167 
168 template <class Iterator, class UnaryFunc>
169 transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it,UnaryFunc fun)170 make_transform_iterator(Iterator it, UnaryFunc fun)
171 {
172    return transform_iterator<Iterator, UnaryFunc>(it, fun);
173 }
174 
175 }  //namespace container {
176 }  //namespace boost {
177 
178 #include <boost/container/detail/config_end.hpp>
179 
180 #endif   //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
181