Brian Silverman | 5962333 | 2018-08-04 23:36:56 -0700 | [diff] [blame^] | 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 | [@../../example/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 | [@../../example/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 | [@../../example/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] |