]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/range/doc/reference/extending.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / range / doc / reference / extending.qbk
CommitLineData
7c673cae
FG
1[/
2 Copyright 2010 Neil Groves
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5/]
6[section:extending Extending the library]
7
8[section:method_1 Method 1: provide member functions and nested types]
9
10This procedure assumes that you have control over the types that should be made conformant to a Range concept. If not, see [link range.reference.extending.method_2 method 2].
11
12The primary templates in this library are implemented such that standard containers will work automatically and so will __boost_array__. Below is given an overview of which member functions and member types a class must specify to be useable as a certain Range concept.
13
14[table
15 [[Member function] [Related concept ]]
16 [[`begin()` ] [__single_pass_range__]]
17 [[`end()` ] [__single_pass_range__]]
18]
19
20Notice that `rbegin()` and `rend()` member functions are not needed even though the container can support bidirectional iteration.
21
22The required member types are:
23
24[table
25 [[Member type ] [Related concept ]]
26 [[`iterator` ] [__single_pass_range__]]
27 [[`const_iterator`] [__single_pass_range__]]
28]
29
30Again one should notice that member types `reverse_iterator` and `const_reverse_iterator` are not needed.
31
32[endsect]
33
34[section:method_2 Method 2: provide free-standing functions and specialize metafunctions]
35
36This procedure assumes that you cannot (or do not wish to) change the types that should be made conformant to a Range concept. If this is not true, see [link range.reference.extending.method_1 method 1].
37
38The primary templates in this library are implemented such that certain functions are found via argument-dependent-lookup (ADL). Below is given an overview of which free-standing functions a class must specify to be useable as a certain Range concept. Let `x` be a variable (`const` or `mutable`) of the class in question.
39
40[table
41 [[Function ] [Related concept ]]
42 [[`range_begin(x)`] [__single_pass_range__]]
43 [[`range_end(x)` ] [__single_pass_range__]]
44 [[`range_calculate_size(x)`] [ Optional. This can be used to specify a mechanism for constant-time computation of the size of a range. The default behaviour is to return `boost::end(x) - boost::begin(x)` for random access ranges, and to return `x.size()` for ranges with lesser traversal capability. This behaviour can be changed by implementing `range_calculate_size` in a manner that will be found via ADL. The ability to calculate size in O(1) is often possible even with ranges with traversal categories less than random access.]]
45]
46
47`range_begin()` and `range_end()` must be overloaded for both `const` and `mutable` reference arguments.
48
49You must also specialize two metafunctions for your type `X`:
50
51[table
52 [[Metafunction ] [Related concept ]]
53 [[`boost::range_mutable_iterator`] [__single_pass_range__]]
54 [[`boost::range_const_iterator`] [__single_pass_range__]]
55]
56
57A complete example is given here:
58
59``
60 #include <boost/range.hpp>
61 #include <iterator> // for std::iterator_traits, std::distance()
62
63 namespace Foo
64 {
65 //
66 // Our sample UDT. A 'Pair'
67 // will work as a range when the stored
68 // elements are iterators.
69 //
70 template< class T >
71 struct Pair
72 {
73 T first, last;
74 };
75
76 } // namespace 'Foo'
77
78 namespace boost
79 {
80 //
81 // Specialize metafunctions. We must include the range.hpp header.
82 // We must open the 'boost' namespace.
83 //
84
85 template< class T >
86 struct range_mutable_iterator< Foo::Pair<T> >
87 {
88 typedef T type;
89 };
90
91 template< class T >
92 struct range_const_iterator< Foo::Pair<T> >
93 {
94 //
95 // Remark: this is defined similar to 'range_iterator'
96 // because the 'Pair' type does not distinguish
97 // between an iterator and a const_iterator.
98 //
99 typedef T type;
100 };
101
102 } // namespace 'boost'
103
104 namespace Foo
105 {
106 //
107 // The required functions. These should be defined in
108 // the same namespace as 'Pair', in this case
109 // in namespace 'Foo'.
110 //
111
112 template< class T >
113 inline T range_begin( Pair<T>& x )
114 {
115 return x.first;
116 }
117
118 template< class T >
119 inline T range_begin( const Pair<T>& x )
120 {
121 return x.first;
122 }
123
124 template< class T >
125 inline T range_end( Pair<T>& x )
126 {
127 return x.last;
128 }
129
130 template< class T >
131 inline T range_end( const Pair<T>& x )
132 {
133 return x.last;
134 }
135
136 } // namespace 'Foo'
137
138 #include <vector>
139
140 int main(int argc, const char* argv[])
141 {
142 typedef std::vector<int>::iterator iter;
143 std::vector<int> vec;
144 Foo::Pair<iter> pair = { vec.begin(), vec.end() };
145 const Foo::Pair<iter>& cpair = pair;
146 //
147 // Notice that we call 'begin' etc with qualification.
148 //
149 iter i = boost::begin( pair );
150 iter e = boost::end( pair );
151 i = boost::begin( cpair );
152 e = boost::end( cpair );
153 boost::range_difference< Foo::Pair<iter> >::type s = boost::size( pair );
154 s = boost::size( cpair );
155 boost::range_reverse_iterator< const Foo::Pair<iter> >::type
156 ri = boost::rbegin( cpair ),
157 re = boost::rend( cpair );
158
159 return 0;
160 }
161``
162
163[endsect]
164
165[section:method_3 Method 3: provide range adaptor implementations]
166
167[section:method_3_1 Method 3.1: Implement a Range Adaptor without arguments]
168
169To implement a Range Adaptor without arguments (e.g. reversed) you need to:
170
171# Provide a range for your return type, for example:
172``
173#include <boost/range/iterator_range.hpp>
174#include <boost/iterator/reverse_iterator.hpp>
175
176template< typename R >
177struct reverse_range :
178 boost::iterator_range<
179 boost::reverse_iterator<
180 typename boost::range_iterator<R>::type> >
181{
182private:
183 typedef boost::iterator_range<
184 boost::reverse_iterator<
185 typename boost::range_iterator<R>::type> > base;
186
187public:
188 typedef boost::reverse_iterator<
189 typename boost::range_iterator<R>::type > iterator;
190
191 reverse_range(R& r)
192 : base(iterator(boost::end(r)), iterator(boost::begin(r)))
193 { }
194};
195``
196
197# Provide a tag to uniquely identify your adaptor in the `operator|` function overload set
198``
199namespace detail {
200 struct reverse_forwarder {};
201}
202``
203
204# Implement `operator|`
205``
206template< class BidirectionalRng >
207inline reverse_range<BidirectionalRng>
208operator|( BidirectionalRng& r, detail::reverse_forwarder )
209{
210 return reverse_range<BidirectionalRng>( r );
211}
212
213template< class BidirectionalRng >
214inline reverse_range<const BidirectionalRng>
215operator|( const BidirectionalRng& r, detail::reverse_forwarder )
216{
217 return reverse_range<const BidirectionalRng>( r );
218}
219``
220
221# Declare the adaptor itself (it is a variable of the tag type).
222``
223namespace
224{
225 const detail::reverse_forwarder reversed = detail::reverse_forwarder();
226}
227``
228
229[endsect]
230
231[section:method_3_2 Method 3.2: Implement a Range Adaptor with arguments]
232
233# Provide a range for your return type, for example:
234``
235#include <boost/range/adaptor/argument_fwd.hpp>
236#include <boost/range/iterator_range.hpp>
237#include <boost/iterator/transform_iterator.hpp>
238
239template<typename Value>
240class replace_value
241{
242public:
243 typedef const Value& result_type;
244 typedef const Value& argument_type;
245
246 replace_value(const Value& from, const Value& to)
247 : m_from(from), m_to(to)
248 {
249 }
250
251 const Value& operator()(const Value& x) const
252 {
253 return (x == m_from) ? m_to : x;
254 }
255private:
256 Value m_from;
257 Value m_to;
258};
259
260template<typename Range>
261class replace_range
262: public boost::iterator_range<
263 boost::transform_iterator<
264 replace_value<typename boost::range_value<Range>::type>,
265 typename boost::range_iterator<Range>::type> >
266{
267private:
268 typedef typename boost::range_value<Range>::type value_type;
269 typedef typename boost::range_iterator<Range>::type iterator_base;
270 typedef replace_value<value_type> Fn;
271 typedef boost::transform_iterator<Fn, iterator_base> replaced_iterator;
272 typedef boost::iterator_range<replaced_iterator> base_t;
273
274public:
275 replace_range(Range& rng, value_type from, value_type to)
276 : base_t(replaced_iterator(boost::begin(rng), Fn(from,to)),
277 replaced_iterator(boost::end(rng), Fn(from,to)))
278 {
279 }
280 };
281``
282
283# Implement a holder class to hold the arguments required to construct the RangeAdaptor.
284The holder combines multiple parameters into one that can be passed as the right operand of `operator|()`.
285``
286template<typename T>
287class replace_holder : public boost::range_detail::holder2<T>
288{
289public:
290 replace_holder(const T& from, const T& to)
291 : boost::range_detail::holder2<T>(from, to)
292 { }
293private:
294 void operator=(const replace_holder&);
295};
296``
297
298# Define an instance of the holder with the name of the adaptor
299``
300static boost::range_detail::forwarder2<replace_holder>
301replaced = boost::range_detail::forwarder2<replace_holder>();
302``
303
304# Define `operator|`
305``
306template<typename SinglePassRange>
307inline replace_range<SinglePassRange>
308operator|(SinglePassRange& rng,
309 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f)
310{
311 return replace_range<SinglePassRange>(rng, f.val1, f.val2);
312}
313
314template<typename SinglePassRange>
315inline replace_range<const SinglePassRange>
316operator|(const SinglePassRange& rng,
317 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f)
318{
319 return replace_range<const SinglePassRange>(rng, f.val1, f.val2);
320}
321``
322
323[endsect]
324
325[endsect]
326
327[endsect]
328