I have a class that holds a list containing boost::shared_ptrs
to objects of another class.
The class member functions that give access to the elemets in the list return raw pointers. For consistency I'd also like to be able to iterate with raw pointers instead of shared_ptrs. So when I dereference the list iterator, I'd like to get raw pointer, not a shared_ptr
.
I assume I need to write a custom iterator for this. Is this correct? If so can someone point me in the right direction - I've never done this before.
The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.
Use shared_ptr to manage the lifetime of objects: Whose ownership is shared (multiple "things" want the object lifetime extended) Where the order of release of ownership is non-deterministic (you don't know in advance which of the owners will be "last" to release the object).
Shared pointers in C++ In C++, a shared pointer is one of the smart pointers. The shared pointer maintains a reference count which is incremented when another shared pointer points to the same object. So, when the reference count is equal to zero (i.e., no pointer points to this object), the object is destroyed.
Here's an option using Boost transform_iterator:
#include <list>
#include <boost/iterator/transform_iterator.hpp>
#include <tr1/memory>
#include <tr1/functional>
using std::list;
using std::tr1::shared_ptr;
using boost::transform_iterator;
using boost::make_transform_iterator;
using std::tr1::mem_fn;
using std::tr1::function;
struct Foo {};
struct Bar
{
typedef shared_ptr< Foo > Ptr;
typedef list< Ptr > List;
typedef function< Foo* (Ptr) > Functor;
typedef transform_iterator< Functor, List::iterator > Iterator;
Iterator begin()
{
return make_transform_iterator( fooptrs.begin(), mem_fn( &Ptr::get ) );
}
Iterator end()
{
return make_transform_iterator( fooptrs.end(), mem_fn( &Ptr::get ) );
}
List fooptrs;
};
C++11 would make it easy to eliminate the function
wrapper but I don't have a compiler handy to test it out. You could also hide the concrete type of Iterator
using type-erasure if you saw the need (I think Adobe offers a free any_iterator
class template for this purpose.)
I sometimes see people reaching for STL containers of boost::shared_ptr
when actually the less obvious and relatively little known boost::ptr_container
might be a better choice.
This may or may not be one of those cases, but consider that one of the nice properties of the ptr_container
classes is that their iterators have an "extra" indirection which helps keep things clean and safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With