2013-03-22 1 views
2

Я пытаюсь реализовать итератор map<T, shared_ptr<U>>, который «удаляет» shared_ptr, то есть разделяет на pair<T, U&>. Мне нужно это, чтобы адаптировать мою обертку по map к диапазону для цикла.косвенный_отражатель для карты <T, shared_ptr <U>>

boost::indirect_iterator похоже на что-то, предназначенное для такой необходимости. Я попытался это:

typedef std::map<int, std::shared_ptr<int>> M; 
typedef boost::indirect_iterator<M::iterator, std::pair<int, int>> It; 

Это не работает из-за indirect_iterator требования:

Выражение * v, где v является объектом iterator_traits :: value_type, должно быть действительным выражением и конвертируются в ссылки ,

Можно ли использовать boost::indirect_iterator для выполнения этой задачи? Если нет, могу ли я сделать это с помощью boost::iterator_adaptor?

+3

'map | boost :: adapters :: map_values ​​| boost :: adapters :: косвенные' – Xeo

ответ

2

Благодаря комментарию @Xeo решение должно использовать Boost.Range. Что мне удалось получить от VC10

#include <boost/range/adaptor/map.hpp> 
#include <boost/range/adaptor/indirected.hpp> 

#if defined(_MSC_VER) && _MSC_VER <= 1600 // VC10 
    template< class T > 
    typename std::add_rvalue_reference<T>::type declval(); 
#endif 

class Wrapper 
{ 
private: 
    typedef std::map<T, std::shared_ptr<U>> Container; 

public: 
    typedef decltype(declval<Container&>() | boost::adaptors::map_values | boost::adaptors::indirected) IteratorRange; 
    typedef decltype(declval<Container&>() | boost::adaptors::map_values | boost::adaptors::indirected) ConstIteratorRange; 
    typedef IteratorRange::iterator Iterator; 
    typedef ConstIteratorRange::const_iterator ConstIterator; 

    Iterator begin() 
    { 
     return iteratorRange().begin(); 
    } 

    // by analogy 
    ConstIterator begin() const; 
    ConstIterator cbegin() const; 
    Iterator end(); 
    ConstIterator end() const; 
    ConstIterator cend() const; 

private: 
    IteratorRange iteratorRange() 
    { 
     return container | boost::adaptors::map_values | boost::adaptors::indirected; 
    } 

    ConstIteratorRange iteratorRange() const; 

private: 
    Container container; 
}; 
+1

Вместо хакерских приемов просто используйте 'declval '. VC10, к сожалению, забыл об этом, но он довольно короткий: 'template typename std :: add_rvalue_reference :: type declval();' - left undefined, поэтому его можно использовать только в неоцененных контекстах. Теперь просто используйте 'decltype (declval () | map_values ​​| косвенные)'. – Xeo

+0

@Xeo: tnx, применяется –