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 be deleted after the last iterator is destroyed. The shared container iterator is typically used to implement functions that return iterators over a range of objects that will only be needed for the lifetime of the iterators. By returning a pair of shared iterators from a function, the callee can ensure that the underlying container's lifetime will be properly managed.
The shared container iterator augments an iterator into a shared container with a reference counted pointer to the container. Assuming no other references exist to the container, it will be destroyed when the last shared container iterator is destroyed. In all other ways, the shared container iterator behaves the same as its base iterator.
namespace boost { template <typename Container> class shared_container_iterator_generator; template <typename Container> typename shared_container_iterator_generator<Container>::type make_shared_container_iterator(typename Container::iterator base, boost::shared_ptr<Container> const& container); std::pair< typename shared_container_iterator_generator<Container>::type, typename shared_container_iterator_generator<Container>::type > make_shared_container_range(boost::shared_ptr<Container> const& container); }
template <typename Container> class shared_container_iterator_generator { public: typedef iterator_adaptor<...> type; };
The following example illustrates how to use the shared_counter_iterator_generator to create an iterator that regulates the lifetime of a reference counted std::vector. Though the original shared_ptr to the vector ceases to exist, the shared_counter_iterators extend the lifetime of the container.
#include "shared_container_iterator.hpp" #include "boost/shared_ptr.hpp" #include <algorithm> #include <iostream> #include <vector> typedef boost::shared_container_iterator_generator< std::vector<int> >::type 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,
Parameter | Description |
---|---|
Container | The type of the container that we wish to iterate over. It must be a model of the Container concept. |
shared_container_iterator_generator::type(Container::iterator const& it, boost::shared_ptr<Container> const& container)
template <typename Container> typename shared_container_iterator_generator<AdaptableUnaryFunction,BaseIterator>::type make_shared_container_iterator(Container::iterator base, boost::shared_ptr<Container> const& container)This function provides an alternative to using the shared container iterator type generator to create the iterator type before construction. Using the object generator, a shared container iterator can be created and passed to a function without explicitly specifying its type.
#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.
template <typename Container> std::pair< typename shared_container_iterator_generator<Container>::type, typename shared_container_iterator_generator<Container>::type > make_shared_container_range(boost::shared_ptr<Container> const& container);Class shared_container_iterator is meant primarily to return via 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. This function is equivalent to
std::make_pair(make_shared_container_iterator(container->begin(),container), make_shared_container_iterator(container->end(),container));
#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_generator< std::vector<int> >::type function_iterator; std::pair<function_iterator,function_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() { function_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.
© Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.