Boost logo

Boost Users :

Subject: Re: [Boost-users] [ptr_container] Const & non-const ptr_map iteration over mapped values.
From: Thorsten Ottosen (thorsten.ottosen_at_[hidden])
Date: 2009-06-15 04:22:56


Rodolfo Federico Gamarra skrev:
> Hi all!!
>
> In my class have an internal member of type
>
> typedef boost::ptr_map<int, Component> InternalComponentCollection;
>
> I'd like to provide const and non-const iterators, through appropriate
> two pairs of begin / end methods, in order to have "const Component&"
> and "Component&" as return type in each of the dereferencing
> operators. What's the way to do that?
>
> What I tried:
>
> Since the underlying storage relies in "pair" with a pointer, I
> thought of using a transform iterator to project "second" and then
> dereference the pointer; something like, for instance,
>
> ComponentIterator Begin() {
> return boost::make_transform_iterator(fComponents.begin(), fResolver);
> }
>
> where fResolver is an instance of
>
> template<class T1, class T2, class R>
> struct SecondResolver {
> typedef R result_type;
> template< template <typename,typename> class Pair>
> result_type operator()(const Pair<T1, const T2>& p) const {
> return * p.second;
> }
> };

I would just implement this as (abbreviated)

template< class R >
struct X
{
   template< class Pair >
   R operator()( const Pair& p ) const { return *p.second; }
};

> and having
>
> typedef SecondResolver<KeyType, MappedType, MappedReference> ComponentResolver;
> typedef typename InternalComponentCollection::key_type KeyType;
> typedef typename InternalComponentCollection::mapped_type MappedType;
> typedef typename InternalComponentCollection::mapped_reference MappedReference;
> typedef typename InternalComponentCollection::iterator PairIterator;
> typedef boost::transform_iterator<ComponentResolver, PairIterator>
> ComponentIterator;
>
> The case for const iteration is similarly implemented, using the
> following typedefs:
>
> typedef SecondResolver<KeyType, ConstMappedType, ConstMappedReference>
> ConstComponentResolver;
> typedef const Component* /* No nested typedef for this...*/ ConstMappedType;
> typedef typename InternalComponentCollection::const_mapped_reference
> ConstMappedReference;
> typedef typename InternalComponentCollection::const_iterato PairConstIterator;
> typedef boost::transform_iterator<ConstComponentResolver, PairConstIterator>
> ComponentConstIterator;
>
> My remarks about my solution are:
>
> 1) SecondResolver is not an "UnaryFunction" in the sense of the C++
> standard, since there's no "argument_type" nested typedef. Tough it
> seems that that isn't actually required by transform_iterator. I have
> problems in trying to define that typedef (see 2).

Well, why do you want to define that typedef, when it is easier to infer
the type automatically?

> 2) The actual pairs are instances of
>
> boost::ptr_container_detail::ref_pair
>
> so it wouldn't be right to typedef that as arg type (it's a "detail").
> This class provides implicit conversion from std::pair, but no
> implicit conversion to std::pair. So that's why I wrote the operator()
> as a template function, since cannot give the operator an explicit
> type: nor ref_pair (being a detail), nor std::pair (not having the
> conversion). Should that conversion be provided?

Why? Dont map::value_type v = *m.find(x) work?

> 3) I wrote ConstMappedType typedef explicitly, without relying in a
> nested typedef in the original class. Doing
>
> typedef const MappedType ConstMappedType;
>
> doesn't work because the const binds to the pointer, not to the pointed type.

Again, why do you want to do this?

-Thorsten


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net