]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | [section:shared_container Shared Container Iterator] | |
3 | ||
4 | Defined in header [@../../../boost/shared_container_iterator.hpp `boost/shared_container_iterator.hpp`]. | |
5 | ||
6 | The purpose of the shared container iterator is to attach the lifetime | |
7 | of a container to the lifetime of its iterators. In other words, the | |
8 | container will not be deleted until after all its iterators are | |
9 | destroyed. The shared container iterator is typically used to | |
10 | implement functions that return iterators over a range of objects that | |
11 | only need to exist for the lifetime of the iterators. By returning a | |
12 | pair of shared iterators from a function, the callee can return a | |
13 | heap-allocated range of objects whose lifetime is automatically | |
14 | managed. | |
15 | ||
16 | The shared container iterator augments an iterator over a shared | |
17 | container. It maintains a reference count on the shared container. If | |
18 | only shared container iterators hold references to the container, the | |
19 | container's lifetime will end when the last shared container iterator | |
20 | over it is destroyed. In any case, the shared container is guaranteed | |
21 | to persist beyond the lifetime of all the iterators. In all other | |
22 | ways, the shared container iterator behaves the same as its base | |
23 | iterator. | |
24 | ||
25 | [h2 Synopsis] | |
26 | ||
27 | namespace boost { | |
28 | template <typename Container> | |
29 | class shared_container_iterator; | |
30 | ||
31 | template <typename Container> | |
32 | shared_container_iterator<Container> | |
33 | make_shared_container_iterator(typename Container::iterator base, | |
34 | boost::shared_ptr<Container> const& container); | |
35 | ||
36 | std::pair< | |
37 | typename shared_container_iterator<Container>, | |
38 | typename shared_container_iterator<Container> | |
39 | > | |
40 | make_shared_container_range(boost::shared_ptr<Container> const& container); | |
41 | } | |
42 | ||
43 | [section:shared_container_type The Shared Container Iterator Type] | |
44 | ||
45 | template <typename Container> class shared_container_iterator; | |
46 | ||
47 | The class template `shared_container_iterator` is the shared container | |
48 | iterator type. The `Container` template type argument must model the | |
49 | [@http://www.sgi.com/tech/stl/Container.html Container] concept. | |
50 | ||
51 | [h2 Example] | |
52 | ||
53 | The following example illustrates how to create an iterator that | |
54 | regulates the lifetime of a reference counted `std::vector`. Though the | |
55 | original shared pointer `ints` ceases to exist after `set_range()` | |
56 | returns, the `shared_counter_iterator` objects maintain references to | |
57 | the underlying vector and thereby extend the container's lifetime. | |
58 | ||
59 | [@../../../libs/utility/shared_iterator_example1.cpp `shared_iterator_example1.cpp`]: | |
60 | ||
61 | #include "shared_container_iterator.hpp" | |
62 | #include "boost/shared_ptr.hpp" | |
63 | #include <algorithm> | |
64 | #include <iostream> | |
65 | #include <vector> | |
66 | ||
67 | typedef boost::shared_container_iterator< std::vector<int> > iterator; | |
68 | ||
69 | ||
70 | void set_range(iterator& i, iterator& end) { | |
71 | ||
72 | boost::shared_ptr< std::vector<int> > ints(new std::vector<int>()); | |
73 | ||
74 | ints->push_back(0); | |
75 | ints->push_back(1); | |
76 | ints->push_back(2); | |
77 | ints->push_back(3); | |
78 | ints->push_back(4); | |
79 | ints->push_back(5); | |
80 | ||
81 | i = iterator(ints->begin(),ints); | |
82 | end = iterator(ints->end(),ints); | |
83 | } | |
84 | ||
85 | ||
86 | int main() { | |
87 | ||
88 | iterator i,end; | |
89 | ||
90 | set_range(i,end); | |
91 | ||
92 | std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | |
93 | std::cout.put('\n'); | |
94 | ||
95 | return 0; | |
96 | } | |
97 | ||
98 | The output from this part is: | |
99 | ||
100 | 0,1,2,3,4,5, | |
101 | ||
102 | [table Template Parameters | |
103 | [[Parameter][Description]] | |
104 | [[Container][The type of the container that we wish to iterate over. It must be a model of the Container concept.]] | |
105 | ] | |
106 | ||
107 | [h2 Concepts] | |
108 | ||
109 | The `shared_container_iterator` type models the same iterator concept | |
110 | as the base iterator (`Container::iterator`). | |
111 | ||
112 | [h2 Operations] | |
113 | ||
114 | The `shared_container_iterator` type implements the member functions | |
115 | and operators required of the | |
116 | [@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access | |
117 | Iterator] concept, though only operations defined for the base | |
118 | iterator will be valid. In addition it has the following constructor: | |
119 | ||
120 | shared_container_iterator(Container::iterator const& it, | |
121 | boost::shared_ptr<Container> const& container) | |
122 | ||
123 | [endsect] | |
124 | ||
125 | [section:shared_container_object_generator The Shared Container Iterator Object Generator] | |
126 | ||
127 | template <typename Container> | |
128 | shared_container_iterator<Container> | |
129 | make_shared_container_iterator(Container::iterator base, | |
130 | boost::shared_ptr<Container> const& container) | |
131 | ||
132 | This function provides an alternative to directly constructing a | |
133 | `shared_container_iterator`. Using the object generator, a | |
134 | `shared_container_iterator` can be created and passed to a function without | |
135 | explicitly specifying its type. | |
136 | ||
137 | [h2 Example] | |
138 | ||
139 | This example, similar to the previous, | |
140 | uses `make_shared_container_iterator()` to create the iterators. | |
141 | ||
142 | [@../../../libs/utility/shared_iterator_example2.cpp `shared_iterator_example2.cpp`]: | |
143 | ||
144 | #include "shared_container_iterator.hpp" | |
145 | #include "boost/shared_ptr.hpp" | |
146 | #include <algorithm> | |
147 | #include <iterator> | |
148 | #include <iostream> | |
149 | #include <vector> | |
150 | ||
151 | ||
152 | template <typename Iterator> | |
153 | void print_range_nl (Iterator begin, Iterator end) { | |
154 | typedef typename std::iterator_traits<Iterator>::value_type val; | |
155 | std::copy(begin,end,std::ostream_iterator<val>(std::cout,",")); | |
156 | std::cout.put('\n'); | |
157 | } | |
158 | ||
159 | ||
160 | int main() { | |
161 | ||
162 | typedef boost::shared_ptr< std::vector<int> > ints_t; | |
163 | { | |
164 | ints_t ints(new std::vector<int>()); | |
165 | ||
166 | ints->push_back(0); | |
167 | ints->push_back(1); | |
168 | ints->push_back(2); | |
169 | ints->push_back(3); | |
170 | ints->push_back(4); | |
171 | ints->push_back(5); | |
172 | ||
173 | print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), | |
174 | boost::make_shared_container_iterator(ints->end(),ints)); | |
175 | } | |
176 | ||
177 | ||
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
182 | Observe that the `shared_container_iterator` type is never explicitly | |
183 | named. The output from this example is the same as the previous. | |
184 | ||
185 | [endsect] | |
186 | ||
187 | [section:shared_container_generator The Shared Container Iterator Range Generator] | |
188 | ||
189 | template <typename Container> | |
190 | std::pair< | |
191 | shared_container_iterator<Container>, | |
192 | shared_container_iterator<Container> | |
193 | > | |
194 | make_shared_container_range(boost::shared_ptr<Container> const& container); | |
195 | Class shared_container_iterator is meant primarily to return, using iterators, a range of values that we can guarantee will be alive as long as the iterators are. This is a convenience function to do just that. It is equivalent to | |
196 | std::make_pair(make_shared_container_iterator(container->begin(),container), | |
197 | make_shared_container_iterator(container->end(),container)); | |
198 | ||
199 | [h2 Example] | |
200 | ||
201 | In the following example, a range of values is returned as a pair of shared_container_iterator objects. | |
202 | ||
203 | [@../../../libs/utility/shared_iterator_example3.cpp `shared_iterator_example3.cpp`]: | |
204 | ||
205 | #include "shared_container_iterator.hpp" | |
206 | #include "boost/shared_ptr.hpp" | |
207 | #include "boost/tuple/tuple.hpp" // for boost::tie | |
208 | #include <algorithm> // for std::copy | |
209 | #include <iostream> | |
210 | #include <vector> | |
211 | ||
212 | ||
213 | typedef boost::shared_container_iterator< std::vector<int> > iterator; | |
214 | ||
215 | std::pair<iterator,iterator> | |
216 | return_range() { | |
217 | boost::shared_ptr< std::vector<int> > range(new std::vector<int>()); | |
218 | range->push_back(0); | |
219 | range->push_back(1); | |
220 | range->push_back(2); | |
221 | range->push_back(3); | |
222 | range->push_back(4); | |
223 | range->push_back(5); | |
224 | return boost::make_shared_container_range(range); | |
225 | } | |
226 | ||
227 | ||
228 | int main() { | |
229 | ||
230 | ||
231 | iterator i,end; | |
232 | ||
233 | boost::tie(i,end) = return_range(); | |
234 | ||
235 | std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | |
236 | std::cout.put('\n'); | |
237 | ||
238 | return 0; | |
239 | } | |
240 | ||
241 | Though the range object only lives for the duration of the | |
242 | `return_range` call, the reference counted `std::vector` will live | |
243 | until `i` and `end` are both destroyed. The output from this example is | |
244 | the same as the previous two. | |
245 | ||
246 | [endsect] | |
247 | ||
248 | [endsect] |