Ticket #4620: enumerate.h

File enumerate.h, 6.6 KB (added by Ilya Murav'jov <muravev@…>, 12 years ago)

enumerate.h

Line 
1// Enumerate adapter for Boost.Range & Foreach
2//
3// Copyright (c) 2010 Ilya Murav'jov
4//
5// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
6// distribution is subject to the Boost Software License, Version
7// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef __MLIB_RANGE_ENUMERATE_H__
12#define __MLIB_RANGE_ENUMERATE_H__
13
14#include <mlib/range/adaptor/argument_fwd.hpp>
15
16#include <boost/range/iterator_range.hpp>
17#include <boost/range/begin.hpp>
18#include <boost/range/end.hpp>
19
20#include <boost/iterator/iterator_traits.hpp>
21#include <boost/iterator/iterator_adaptor.hpp>
22
23//#include <utility> // std::pair
24#include <boost/tuple/tuple.hpp>
25
26namespace boost
27{
28 namespace adaptors
29 {
30 struct enumerated
31 {
32 explicit enumerated(std::size_t x = std::size_t()) : val(x) {}
33 std::size_t val;
34 };
35 }
36
37 // Why yet another "pair" class:
38 // - std::pair can't store references
39 // - no need for typing for index type (default to "int"); this is extremely useful
40 // in BOOST_FOREACH() expressions that have pitfalls with commas
41 // ( see http://www.boost.org/doc/libs/1_44_0/doc/html/foreach/pitfalls.html )
42 // - meaningful access functions index(), value()
43 template<class T, class Indexable = ptrdiff_t>
44 class index_value: public tuple<Indexable, T>
45 {
46 public:
47 typedef tuple<Indexable, T> super_t;
48
49 template <int N>
50 struct iv_types
51 {
52 typedef typename tuples::element<N, super_t>::type n_type;
53
54 typedef typename tuples::access_traits<n_type>::non_const_type non_const_type;
55 typedef typename tuples::access_traits<n_type>::const_type const_type;
56 };
57
58 index_value() {}
59
60 index_value(typename tuples::access_traits<Indexable>::parameter_type t0,
61 typename tuples::access_traits<T>::parameter_type t1)
62 : super_t(t0, t1) {}
63
64 // member functions index(), value() (non-const and const)
65 typename iv_types<0>::non_const_type
66 index() { return boost::tuples::get<0>(*this); }
67
68 typename iv_types<0>::const_type
69 index() const { return boost::tuples::get<0>(*this); }
70
71 typename iv_types<1>::non_const_type
72 value() { return boost::tuples::get<1>(*this); }
73
74 typename iv_types<1>::const_type
75 value() const { return boost::tuples::get<1>(*this); }
76 };
77
78 namespace range_detail
79 {
80 template<typename Iter>
81 class enumerated_iterator;
82
83 // like zip_iterator!
84 template<typename Iterator>
85 struct enumerated_iterator_base
86 {
87 private:
88 typedef typename iterator_reference<Iterator>::type iterator_reference;
89 typedef typename iterator_difference<Iterator>::type difference_type;
90 typedef index_value<iterator_reference, difference_type> reference;
91
92 typedef reference value_type;
93 typedef typename iterator_category<Iterator>::type iterator_category;
94 public:
95
96 typedef iterator_adaptor<
97 enumerated_iterator<Iterator>,
98 Iterator,
99 value_type,
100 use_default, // let it be the same
101 reference,
102 difference_type
103 > type;
104 };
105
106 template<typename Iter>
107 class enumerated_iterator: public enumerated_iterator_base<Iter>::type
108 {
109 private:
110 typedef BOOST_DEDUCED_TYPENAME enumerated_iterator_base<Iter>::type super_t;
111
112 typedef BOOST_DEDUCED_TYPENAME super_t::difference_type index_type;
113
114 index_type m_index;
115
116 public:
117 typedef BOOST_DEDUCED_TYPENAME super_t::reference reference;
118
119 explicit enumerated_iterator( Iter i, index_type index )
120 : super_t(i), m_index(index)
121 {
122 BOOST_ASSERT( m_index >= 0 && "Indexed Iterator out of bounds" );
123 }
124
125 private:
126 friend class boost::iterator_core_access;
127
128 reference dereference() const
129 {
130 return reference(m_index, *this->base());
131 }
132
133 void increment()
134 {
135 ++m_index;
136 ++(this->base_reference());
137 }
138
139 void decrement()
140 {
141 BOOST_ASSERT( m_index > 0 && "enumerated Iterator out of bounds" );
142 --m_index;
143 --(this->base_reference());
144 }
145
146 void advance( index_type n )
147 {
148 m_index += n;
149 BOOST_ASSERT( m_index >= 0 && "enumerated Iterator out of bounds" );
150 this->base_reference() += n;
151 }
152 };
153
154 template< class Rng >
155 struct enumerated_range :
156 iterator_range< enumerated_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> >
157 {
158 private:
159 typedef enumerated_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type>
160 iter_type;
161 typedef iterator_range<iter_type>
162 base;
163 public:
164 template< class Index >
165 enumerated_range( Index i, Rng& r )
166 : base( iter_type(boost::begin(r), i), iter_type(boost::end(r),i) )
167 { }
168 };
169
170 } // 'range_detail'
171 using range_detail::enumerated_range;
172
173 namespace adaptors
174 {
175 template< class SinglePassRange >
176 inline enumerated_range<SinglePassRange>
177 operator|( SinglePassRange& r,
178 const enumerated& f )
179 {
180 return enumerated_range<SinglePassRange>( f.val, r );
181 }
182
183 template< class SinglePassRange >
184 inline enumerated_range<const SinglePassRange>
185 operator|( const SinglePassRange& r,
186 const enumerated& f )
187 {
188 return enumerated_range<const SinglePassRange>( f.val, r );
189 }
190
191 template<class SinglePassRange, class Index>
192 inline enumerated_range<SinglePassRange>
193 enumerate(SinglePassRange& rng, Index index_value = Index())
194 {
195 return enumerated_range<SinglePassRange>(index_value, rng);
196 }
197
198 template<class SinglePassRange, class Index>
199 inline enumerated_range<const SinglePassRange>
200 enumerate(const SinglePassRange& rng, Index index_value = Index())
201 {
202 return enumerated_range<const SinglePassRange>(index_value, rng);
203 }
204 } // 'adaptors'
205
206}
207
208namespace fe {
209using boost::index_value;
210using boost::adaptors::enumerate;
211using boost::adaptors::enumerated;
212}
213
214#endif // __MLIB_RANGE_ENUMERATE_H__
215