std::set of boost::weak_ptr‹T› — Преобразование const_iterator в const T?

У меня есть класс, содержащий std::set из boost::weak_ptr<T>. У меня есть две функции begin() и end(), которые возвращают итератор в контейнер. Однако я не хочу, чтобы клиенты могли изменять T. Простое возвращение const_iterator не сработает, потому что T, на которое указывает boost::weak_ptr, будет редактируемым.

Что я хочу сделать, так это вернуть const_iterator в std::set<boost::weak_ptr<T const> >. Кастинг от std::set<boost::weak_ptr<T> >::const_iterator не работает. Есть ли способ получить поведение, которое я хочу?


person AVH    schedule 26.03.2011    source источник
comment
Ваши эти два утверждения кажутся противоречивыми: 1) я не хочу, чтобы клиенты могли изменять T и 2) потому что T, на который указывает boost::weak_ptr, будет редактируемым.< /я>. Что это значит?   -  person Nawaz    schedule 26.03.2011
comment
@Nawaz Я имею в виду следующее: возврат const_iterator в std::set<boost::weak_ptr<T> > делает так, что клиент не может изменить weak_ptr. Однако он все еще может получить из него shared_ptr<T>, а затем изменить T по своему желанию. Чего я точно не хочу.   -  person AVH    schedule 27.03.2011


Ответы (1)


Вы можете написать итератор преобразования, чтобы преобразовать weak_ptr<T> в weak_ptr<const T>. Поскольку вы уже используете Boost, вы можете использовать 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;
};

Если вы не хотите использовать boost::transform_iterator, написать свой собственный несложно. Я показал, как это сделать в ответ на другой вопрос.

person James McNellis    schedule 26.03.2011
comment
Спасибо, я и не знал, что такая функция существует. Это потрясающе! - person AVH; 27.03.2011