mirror of
				https://github.com/boostorg/iterator.git
				synced 2025-10-31 16:31:39 +01:00 
			
		
		
		
	
		
			
	
	
		
			248 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			248 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | 
 | ||
|  | [section:shared_container Shared Container Iterator] | ||
|  | 
 | ||
|  | Defined in header [@../../../boost/shared_container_iterator.hpp `boost/shared_container_iterator.hpp`]. | ||
|  | 
 | ||
|  | The purpose of the shared container iterator is to attach the lifetime | ||
|  | of a container to the lifetime of its iterators. In other words, the | ||
|  | container will not be deleted until after all its iterators are | ||
|  | destroyed. The shared container iterator is typically used to | ||
|  | implement functions that return iterators over a range of objects that | ||
|  | only need to exist for the lifetime of the iterators. By returning a | ||
|  | pair of shared iterators from a function, the callee can return a | ||
|  | heap-allocated range of objects whose lifetime is automatically | ||
|  | managed. | ||
|  | 
 | ||
|  | The shared container iterator augments an iterator over a shared | ||
|  | container. It maintains a reference count on the shared container. If | ||
|  | only shared container iterators hold references to the container, the | ||
|  | container's lifetime will end when the last shared container iterator | ||
|  | over it is destroyed. In any case, the shared container is guaranteed | ||
|  | to persist beyond the lifetime of all the iterators. In all other | ||
|  | ways, the shared container iterator behaves the same as its base | ||
|  | iterator. | ||
|  | 
 | ||
|  | [h2 Synopsis] | ||
|  | 
 | ||
|  |   namespace boost { | ||
|  |     template <typename Container> | ||
|  |     class shared_container_iterator; | ||
|  |     | ||
|  |     template <typename Container> | ||
|  |     shared_container_iterator<Container> | ||
|  |     make_shared_container_iterator(typename Container::iterator base,  | ||
|  |       boost::shared_ptr<Container> const& container); | ||
|  |     | ||
|  |     std::pair< | ||
|  |       typename shared_container_iterator<Container>, | ||
|  |       typename shared_container_iterator<Container> | ||
|  |     > | ||
|  |     make_shared_container_range(boost::shared_ptr<Container> const& container); | ||
|  |   } | ||
|  | 
 | ||
|  | [section:shared_container_type The Shared Container Iterator Type] | ||
|  | 
 | ||
|  |   template <typename Container> class shared_container_iterator; | ||
|  | 
 | ||
|  | The class template `shared_container_iterator` is the shared container | ||
|  | iterator type. The `Container` template type argument must model the | ||
|  | [@http://www.sgi.com/tech/stl/Container.html Container] concept.  | ||
|  | 
 | ||
|  | [h2 Example] | ||
|  | 
 | ||
|  | The following example illustrates how to create an iterator that | ||
|  | regulates the lifetime of a reference counted `std::vector`. Though the | ||
|  | original shared pointer `ints` ceases to exist after `set_range()` | ||
|  | returns, the `shared_counter_iterator` objects maintain references to | ||
|  | the underlying vector and thereby extend the container's lifetime. | ||
|  | 
 | ||
|  | [@../../../libs/utility/shared_iterator_example1.cpp `shared_iterator_example1.cpp`]: | ||
|  | 
 | ||
|  |   #include "shared_container_iterator.hpp" | ||
|  |   #include "boost/shared_ptr.hpp" | ||
|  |   #include <algorithm> | ||
|  |   #include <iostream> | ||
|  |   #include <vector> | ||
|  |     | ||
|  |   typedef boost::shared_container_iterator< std::vector<int> > iterator; | ||
|  |     | ||
|  |     | ||
|  |   void set_range(iterator& i, iterator& end)  { | ||
|  |     | ||
|  |     boost::shared_ptr< std::vector<int> > ints(new std::vector<int>()); | ||
|  |      | ||
|  |     ints->push_back(0); | ||
|  |     ints->push_back(1); | ||
|  |     ints->push_back(2); | ||
|  |     ints->push_back(3); | ||
|  |     ints->push_back(4); | ||
|  |     ints->push_back(5); | ||
|  |      | ||
|  |     i = iterator(ints->begin(),ints); | ||
|  |     end = iterator(ints->end(),ints); | ||
|  |   } | ||
|  |     | ||
|  |     | ||
|  |   int main() { | ||
|  |     | ||
|  |     iterator i,end; | ||
|  |     | ||
|  |     set_range(i,end); | ||
|  |     | ||
|  |     std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | ||
|  |     std::cout.put('\n'); | ||
|  |     | ||
|  |     return 0; | ||
|  |   } | ||
|  | 
 | ||
|  | The output from this part is: | ||
|  | 
 | ||
|  |   0,1,2,3,4,5, | ||
|  | 
 | ||
|  | [table Template Parameters | ||
|  |   [[Parameter][Description]] | ||
|  |   [[Container][The type of the container that we wish to iterate over. It must be a model of the Container concept.]] | ||
|  | ] | ||
|  | 
 | ||
|  | [h2 Concepts] | ||
|  | 
 | ||
|  | The `shared_container_iterator` type models the same iterator concept | ||
|  | as the base iterator (`Container::iterator`). | ||
|  | 
 | ||
|  | [h2 Operations] | ||
|  | 
 | ||
|  | The `shared_container_iterator` type implements the member functions | ||
|  | and operators required of the | ||
|  | [@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access | ||
|  | Iterator] concept, though only operations defined for the base | ||
|  | iterator will be valid. In addition it has the following constructor: | ||
|  | 
 | ||
|  |   shared_container_iterator(Container::iterator const& it, | ||
|  |                             boost::shared_ptr<Container> const& container) | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:shared_container_object_generator The Shared Container Iterator Object Generator] | ||
|  | 
 | ||
|  |   template <typename Container> | ||
|  |   shared_container_iterator<Container> | ||
|  |   make_shared_container_iterator(Container::iterator base, | ||
|  |                                  boost::shared_ptr<Container> const& container) | ||
|  | 
 | ||
|  | This function provides an alternative to directly constructing a | ||
|  | `shared_container_iterator`. Using the object generator, a  | ||
|  | `shared_container_iterator` can be created and passed to a function without | ||
|  | explicitly specifying its type. | ||
|  | 
 | ||
|  | [h2 Example] | ||
|  | 
 | ||
|  | This example, similar to the previous,  | ||
|  | uses `make_shared_container_iterator()` to create the iterators. | ||
|  | 
 | ||
|  | [@../../../libs/utility/shared_iterator_example2.cpp `shared_iterator_example2.cpp`]: | ||
|  | 
 | ||
|  |   #include "shared_container_iterator.hpp" | ||
|  |   #include "boost/shared_ptr.hpp" | ||
|  |   #include <algorithm> | ||
|  |   #include <iterator> | ||
|  |   #include <iostream> | ||
|  |   #include <vector> | ||
|  |     | ||
|  |     | ||
|  |   template <typename Iterator> | ||
|  |   void print_range_nl (Iterator begin, Iterator end) { | ||
|  |     typedef typename std::iterator_traits<Iterator>::value_type val; | ||
|  |     std::copy(begin,end,std::ostream_iterator<val>(std::cout,",")); | ||
|  |     std::cout.put('\n'); | ||
|  |   } | ||
|  |     | ||
|  |     | ||
|  |   int main() { | ||
|  |     | ||
|  |     typedef boost::shared_ptr< std::vector<int> > ints_t; | ||
|  |     { | ||
|  |       ints_t ints(new std::vector<int>()); | ||
|  |     | ||
|  |       ints->push_back(0); | ||
|  |       ints->push_back(1); | ||
|  |       ints->push_back(2); | ||
|  |       ints->push_back(3); | ||
|  |       ints->push_back(4); | ||
|  |       ints->push_back(5); | ||
|  |     | ||
|  |       print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), | ||
|  |                      boost::make_shared_container_iterator(ints->end(),ints)); | ||
|  |     } | ||
|  |      | ||
|  |     | ||
|  |     | ||
|  |     return 0; | ||
|  |   } | ||
|  | 
 | ||
|  | Observe that the `shared_container_iterator` type is never explicitly | ||
|  | named. The output from this example is the same as the previous. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:shared_container_generator The Shared Container Iterator Range Generator] | ||
|  | 
 | ||
|  |   template <typename Container> | ||
|  |   std::pair< | ||
|  |     shared_container_iterator<Container>, | ||
|  |     shared_container_iterator<Container> | ||
|  |   > | ||
|  |   make_shared_container_range(boost::shared_ptr<Container> const& container); | ||
|  |   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 | ||
|  |   std::make_pair(make_shared_container_iterator(container->begin(),container), | ||
|  |                  make_shared_container_iterator(container->end(),container)); | ||
|  | 
 | ||
|  | [h2 Example] | ||
|  | 
 | ||
|  | In the following example, a range of values is returned as a pair of shared_container_iterator objects. | ||
|  | 
 | ||
|  | [@../../../libs/utility/shared_iterator_example3.cpp `shared_iterator_example3.cpp`]: | ||
|  | 
 | ||
|  |   #include "shared_container_iterator.hpp" | ||
|  |   #include "boost/shared_ptr.hpp" | ||
|  |   #include "boost/tuple/tuple.hpp" // for boost::tie | ||
|  |   #include <algorithm>              // for std::copy | ||
|  |   #include <iostream>               | ||
|  |   #include <vector> | ||
|  |     | ||
|  |     | ||
|  |   typedef boost::shared_container_iterator< std::vector<int> > iterator;  | ||
|  |     | ||
|  |   std::pair<iterator,iterator> | ||
|  |   return_range() { | ||
|  |     boost::shared_ptr< std::vector<int> > range(new std::vector<int>()); | ||
|  |     range->push_back(0); | ||
|  |     range->push_back(1); | ||
|  |     range->push_back(2); | ||
|  |     range->push_back(3); | ||
|  |     range->push_back(4); | ||
|  |     range->push_back(5); | ||
|  |     return boost::make_shared_container_range(range); | ||
|  |   } | ||
|  |     | ||
|  |     | ||
|  |   int main() { | ||
|  |     | ||
|  |     | ||
|  |     iterator i,end; | ||
|  |      | ||
|  |     boost::tie(i,end) = return_range(); | ||
|  |     | ||
|  |     std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | ||
|  |     std::cout.put('\n'); | ||
|  |     | ||
|  |     return 0; | ||
|  |   } | ||
|  | 
 | ||
|  | Though the range object only lives for the duration of the | ||
|  | `return_range` call, the reference counted `std::vector` will live | ||
|  | until `i` and `end` are both destroyed. The output from this example is | ||
|  | the same as the previous two. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [endsect] |