1 // Boost.Range library
2 //
3 //  Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
4 //  distribution is subject to the Boost Software License, Version
5 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // For more information, see http://www.boost.org/libs/range/
9 //
10 
11 #ifndef BOOST_RANGE_ADAPTOR_INDEXED_IMPL_HPP
12 #define BOOST_RANGE_ADAPTOR_INDEXED_IMPL_HPP
13 
14 #include <boost/config.hpp>
15 #ifdef BOOST_MSVC
16 #pragma warning( push )
17 #pragma warning( disable : 4355 )
18 #endif
19 
20 #include <boost/range/adaptor/argument_fwd.hpp>
21 #include <boost/range/iterator_range.hpp>
22 #include <boost/range/begin.hpp>
23 #include <boost/range/end.hpp>
24 #include <boost/iterator/iterator_adaptor.hpp>
25 
26 
27 
28 namespace boost
29 {
30     namespace adaptors
31     {
32         // This structure exists to carry the parameters from the '|' operator
33         // to the index adapter. The expression rng | indexed(1) instantiates
34         // this structure and passes it as the right-hand operand to the
35         // '|' operator.
36         struct indexed
37         {
indexedboost::adaptors::indexed38             explicit indexed(std::size_t x) : val(x) {}
39             std::size_t val;
40         };
41     }
42 
43     namespace range_detail
44     {
45         template< class Iter >
46         class indexed_iterator
47             : public boost::iterator_adaptor< indexed_iterator<Iter>, Iter >
48         {
49         private:
50             typedef boost::iterator_adaptor< indexed_iterator<Iter>, Iter >
51                   base;
52 
53             typedef BOOST_DEDUCED_TYPENAME base::difference_type index_type;
54 
55             index_type m_index;
56 
57         public:
indexed_iterator(Iter i,index_type index)58             explicit indexed_iterator( Iter i, index_type index )
59             : base(i), m_index(index)
60             {
61                 BOOST_ASSERT( m_index >= 0 && "Indexed Iterator out of bounds" );
62             }
63 
index() const64             index_type index() const
65             {
66                 return m_index;
67             }
68 
69          private:
70             friend class boost::iterator_core_access;
71 
increment()72             void increment()
73             {
74                 ++m_index;
75                 ++(this->base_reference());
76             }
77 
78 
decrement()79             void decrement()
80             {
81                 BOOST_ASSERT( m_index > 0 && "Indexed Iterator out of bounds" );
82                 --m_index;
83                 --(this->base_reference());
84             }
85 
advance(index_type n)86             void advance( index_type n )
87             {
88                 m_index += n;
89                 BOOST_ASSERT( m_index >= 0 && "Indexed Iterator out of bounds" );
90                 this->base_reference() += n;
91             }
92         };
93 
94         template< class Rng >
95         struct indexed_range :
96             iterator_range< indexed_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> >
97         {
98         private:
99             typedef indexed_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type>
100                 iter_type;
101             typedef iterator_range<iter_type>
102                 base;
103         public:
104             template< class Index >
indexed_rangeboost::range_detail::indexed_range105             indexed_range( Index i, Rng& r )
106               : base( iter_type(boost::begin(r), i), iter_type(boost::end(r),i) )
107             { }
108         };
109 
110     } // 'range_detail'
111 
112     // Make this available to users of this library. It will sometimes be
113     // required since it is the return type of operator '|' and
114     // index().
115     using range_detail::indexed_range;
116 
117     namespace adaptors
118     {
119         template< class SinglePassRange >
120         inline indexed_range<SinglePassRange>
operator |(SinglePassRange & r,const indexed & f)121         operator|( SinglePassRange& r,
122                    const indexed& f )
123         {
124             return indexed_range<SinglePassRange>( f.val, r );
125         }
126 
127         template< class SinglePassRange >
128         inline indexed_range<const SinglePassRange>
operator |(const SinglePassRange & r,const indexed & f)129         operator|( const SinglePassRange& r,
130                    const indexed& f )
131         {
132             return indexed_range<const SinglePassRange>( f.val, r );
133         }
134 
135         template<class SinglePassRange, class Index>
136         inline indexed_range<SinglePassRange>
index(SinglePassRange & rng,Index index_value)137         index(SinglePassRange& rng, Index index_value)
138         {
139             return indexed_range<SinglePassRange>(index_value, rng);
140         }
141 
142         template<class SinglePassRange, class Index>
143         inline indexed_range<const SinglePassRange>
index(const SinglePassRange & rng,Index index_value)144         index(const SinglePassRange& rng, Index index_value)
145         {
146             return indexed_range<const SinglePassRange>(index_value, rng);
147         }
148     } // 'adaptors'
149 
150 }
151 
152 #ifdef BOOST_MSVC
153 #pragma warning( pop )
154 #endif
155 
156 #endif
157