boost :: bimap shared_ptr и boost :: transform_iterator

У меня есть контейнер boost::bimap<int, boost::shared_ptr<A>>, и я хочу вернуть итератор в левое представление, обеспечивая постоянство содержимого. Возврат container.left.begin() возвращает итератор, разыменованный на std::pair<int const, boost::shared_ptr<A> const>.

Очевидно, это не то, что я хочу, поскольку можно изменить A, разыменовав shared_ptr. Мне нужен итератор, который разыменовывается на std::pair<int const, boost::shared_ptr<A const>> (мне все равно, является ли shared_ptr константой или нет). Я знаю, что мне, вероятно, следует сделать это с помощью boost :: transform_iterator, но я не могу понять, как должна выглядеть функция "приведения".

Кто-нибудь может мне с этим помочь? Или есть другой, более простой способ получить то, что я хочу?

Редактировать: Вот что у меня есть, достаточно сказать, это дает мне два хороших экрана с ошибками.

typedef boost::bimap<unsigned int, boost::shared_ptr<A> > container_type;
typedef container_type::left_const_iterator base_const_iterator;
typedef boost::transform_iterator<makeIterConst<A>, base_const_iterator> const_iterator;

template <typename T>
struct makeIterConst : std::unary_function<std::pair<unsigned int const, boost::shared_ptr<T> const>, std::pair<unsigned int const, boost::shared_ptr<T const> const> >
{
  std::pair<unsigned int const, boost::shared_ptr<T const> const> operator() (std::pair<int const, boost::shared_ptr<T> const> const & orig) const
  {
    std::pair<int const, boost::shared_ptr<T const> const> newPair(orig.first, boost::const_pointer_cast<T const>(orig.second));
    return newPair;
  }
};

Вот "основная" ошибка:

примечание: функция-кандидат нежизнеспособна: неизвестное преобразование из 'const boost :: bimaps :: Relations :: structured_pair, boost :: bimaps :: tags :: tagged, boost :: bimaps :: Relations :: member_at :: right>, mpl _ :: na, boost :: bimaps :: Relations :: normal_layout> 'to' const std :: pair> 'для 1-го аргумента


person AVH    schedule 25.04.2011    source источник


Ответы (1)


Проблема в том, что ваш value_type не на самом деле std::pair (и не может быть неявно преобразован в него), и поэтому не может быть передан в makeIterConst::operator().

Сделайте так, чтобы вместо этого использовалось const base_const_iterator::value_type &.

#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bimap.hpp>
#include <boost/iterator/transform_iterator.hpp>

struct A
{
    std::string data;
    A(const std::string& s) : data(s) {}
};

typedef boost::bimap<unsigned int, boost::shared_ptr<A> > container_type;
typedef container_type::left_map::const_iterator base_const_iterator;

template <typename T>
struct makeIterConst : std::unary_function<base_const_iterator::value_type const &,
                                           std::pair<unsigned int const, boost::shared_ptr<T const> const> >
{
     std::pair<unsigned int const, boost::shared_ptr<T const> const> operator()
             (base_const_iterator::value_type const & orig) const
     {
         std::pair<int const, boost::shared_ptr<T const> const> newPair(orig.first, boost::const_pointer_cast<T const>(orig.second));
         return newPair;
     }
};

typedef boost::transform_iterator<makeIterConst<A>,
                                 base_const_iterator> const_iterator;

int main()
{
    container_type m;
    boost::shared_ptr<A> p = boost::make_shared<A>("foo");
    m.insert( container_type::value_type(1, p));

//  using regular iterator
    for( base_const_iterator left_iter = m.left.begin();
                         left_iter != m.left.end();
                         ++left_iter )
    {
        std::cout << left_iter->first << " --> " << left_iter->second->data << '\n';
        left_iter->second->data =  "bar"; // compiles
    }

    // using constified iterator
    for( const_iterator left_iter = boost::make_transform_iterator(m.left.begin(), makeIterConst<A>() );
              left_iter != boost::make_transform_iterator(m.left.end(), makeIterConst<A>() );
            ++left_iter )
    {
        std::cout << left_iter->first << " --> " << left_iter->second->data << '\n';
//   the following will give a compilation error, as expected
//      left_iter->second->data =  "changed_foo";
    }
}

тест: https://ideone.com/fHIUe

person Cubbi    schedule 25.04.2011