I'm trying to implement an iterator of map<T, shared_ptr<U>>
that "removes" shared_ptr
, i.e. dereferences to pair<T, U&>
. I need this to adapt my wrapper over map
to range-based for loop.
boost::indirect_iterator
seems like something designed for such a need. I tried this:
typedef std::map<int, std::shared_ptr<int>> M;
typedef boost::indirect_iterator<M::iterator, std::pair<int, int>> It;
This doesn't work because of indirect_iterator
requirement:
The expression *v, where v is an object of iterator_traits::value_type, shall be valid expression and convertible to reference.
Is it possible to use boost::indirect_iterator
for this task? If no, can I do this with boost::iterator_adaptor
?
Thanks to @Xeo comment, the solution is to use Boost.Range. What I managed to get from 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;
};