итератор преобразования с картой unique_ptr

У меня есть класс Holder, который должен отображать только значения своей карты. Для этого я использовал итератор преобразования. Это работает, если я использую простой указатель на тип (ClassA*), но не с unique_ptr. Я создал следующий пример на основе этого кода: проблема компиляции с преобразованием_iterator

Я получаю следующую ошибку (происходящую из функции begin()), что позволяет мне думать, что кто-то пытается скопировать пару вместо использования ссылки.

заранее спасибо

ошибка C2248:
'std::unique_ptr<ClassA,std::default_delete<_Ty>>::unique_ptr':
невозможно получить доступ к частному члену, объявленному в классе
'std::unique_ptr<ClassA,std::default_delete<_Ty>>'

#include <iostream>
#include <map>
#include <functional>
#include <memory>
#include <string>
#include <boost/iterator/transform_iterator.hpp>

struct ClassA
{
    ClassA( const std::string& strName ) : m_strName( strName ) {}
    std::string m_strName;
};

template <typename K, typename V>
const V & get_value(std::pair<K, V> const & p)  { return p.second; }

class Holder
{
    typedef std::map<int, std::unique_ptr< ClassA > > TMap;
    typedef std::unique_ptr< ClassA > UniqueA;
    TMap m_Map;
public:
    Holder()
    {
        UniqueA a( new ClassA( "#2# ") );
        UniqueA b( new ClassA( "#3# ") );
        UniqueA c( new ClassA( "#4# ") );
        m_Map.insert( std::make_pair( 2, std::move( a ) ) );
        m_Map.insert( std::make_pair( 3, std::move( b ) ) );
        m_Map.insert( std::make_pair( 4, std::move( c ) ) );
    }
    typedef std::function< const TMap::mapped_type & (const TMap::value_type &) > F;
    typedef boost::transform_iterator<F, TMap::iterator> transform_iterator;

    transform_iterator begin()
    {
        return boost::make_transform_iterator(m_Map.begin(), &get_value< int, std::unique_ptr< ClassA > >);
    }
    transform_iterator end()
    {
        return boost::make_transform_iterator(m_Map.end(), &get_value< int, std::unique_ptr< ClassA > >);
    }
};

void MyTest()
{
    Holder bla;
    auto s_beg = bla.begin();
    auto s_end = bla.end();
    for( auto t=s_beg; t!=s_end;++t) {
        std::cout << ( *t )->m_strName << std::endl;
    }
}

person Katrin Meerschwein    schedule 04.06.2013    source источник
comment
В какой строке сообщается об ошибке?   -  person n. 1.8e9-where's-my-share m.    schedule 04.06.2013


Ответы (1)


Проблема в том, что get_value принимает ссылку на pair<K,V>, но передает ссылку на тип значения карты, pair<const K,V>. Для этого требуется преобразование, которое требует копирования ключа и значения в новую пару. Вы получаете сообщение об ошибке, потому что unique_ptr невозможно скопировать.

Решение 1: измените get_value, чтобы принять ссылку на pair<const K,V> для соответствия TMap::value_type. Это позволяет функции напрямую принимать ссылки на значения карты.

Решение 2. Создайте экземпляр get_value для const int, а не int; это будет иметь тот же эффект, что и решение 1.

Решение 3. Создайте экземпляр get_value вместо const unique_ptr &, а не unique_ptr, чтобы он принимал пару, содержащую ссылку на значение карты. Эту временную пару можно создать без копирования файла unique_ptr.

person Mike Seymour    schedule 04.06.2013
comment
Решение 1 сработало (другие не проверял)! спасибо, ты спас мой день. - person Katrin Meerschwein; 04.06.2013