Question

I have class containing an std::set of boost::weak_ptr<T>. I have two functions begin() and end() that return an iterator to the container. However, I don't want clients to be able to modify T. Simply returning a const_iterator won't work, because the T pointed to by the boost::weak_ptr will be editable.

What I want to do is return a const_iterator to std::set<boost::weak_ptr<T const> >. Casting from std::set<boost::weak_ptr<T> >::const_iterator does not work. Is there any way to get the behaviour I want?

Was it helpful?

Solution

You can write a transform iterator to convert the weak_ptr<T> to a weak_ptr<const T>. Since you're already using Boost, you can use boost::transform_iterator:

#include <boost/iterator/transform_iterator.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

#include <set>

// Functor to transform a weak_ptr<T> to a weak_ptr<const T>
template <typename T>
struct make_weak_ptr_const
    : std::unary_function<boost::weak_ptr<T>, boost::weak_ptr<const T> >
{
    boost::weak_ptr<const T> operator()(const boost::weak_ptr<T>& p) const
    {
        return p;
    }
};

struct S { };

// Container demonstrating use of make_weak_ptr_const:
struct my_awesome_container
{
    typedef std::set<boost::weak_ptr<S> > BaseSet;
    typedef BaseSet::const_iterator       BaseIterator;

    typedef boost::transform_iterator<
                make_weak_ptr_const<S>, 
                BaseIterator
            > iterator;

    iterator begin() const 
    {
        return TransformedIterator(data.begin());
    }

    iterator end() const
    {
        return TransformedIterator(data.end());
    }

    std::set<boost::weak_ptr<S> > data;
};

If you don't want to use boost::transform_iterator, it is a straightforward task to write your own. I showed how to do this in an answer to another question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top