iterator_adaptor problem (mpl?)

Consider a container such as std::vector<std::pair<int, std::string> > my_container; I want to be able to iterate over the ints of this container so, following the tutorial to the iterator_adaptor docs, came up with template <typename BaseIterator> class first_iter : public boost::iterator_adaptor< first_iter<BaseIterator>, BaseIterator, boost::use_default, boost::use_default, typename BaseIterator::value_type::first_type & > { // snip body }; This works fine so long as BaseIterator::value_type is not const, but falls over when it is because I've defined the 'super_t::reference' type to be mutable. I guess that I need a piece of metafunction magic, but my naive implementation fails typename boost::mpl::apply_if< boost::is_const<typename BaseIterator::value_type> , typename BaseIterator::value_type::first_type const & , typename BaseIterator::value_type::first_type & >::type trial.C:38: error: no type named `type' in `struct boost::mpl::apply_if< boost::is_const<std::pair<int, std::string> >, const int&, int&>' I must admit I'm a bit baffled. There plainly is a 'type' in the apply_if class template. Any pointers? I attach the code as I have it. While I'm at it, is there not something in the MPL that will return the appropriate const-qualified reference for me? None of the header file names in boost/mpl jump out and grab me, but I may well be looking in the wrong place. Regards, Angus

Angus Leeming <angus.leeming@btopenworld.com> writes:
Consider a container such as std::vector<std::pair<int, std::string> > my_container;
I want to be able to iterate over the ints of this container so, following the tutorial to the iterator_adaptor docs, came up with
template <typename BaseIterator> class first_iter : public boost::iterator_adaptor< first_iter<BaseIterator>, BaseIterator, boost::use_default, boost::use_default, typename BaseIterator::value_type::first_type & > { // snip body };
Why struggle? boost::transform_iterator should give you just what you need: struct select1st { template <class P> P::first_type& operator()(P& pair) { return pair.first; } template <class P> P::first_type const& operator()(P const& pair) { return pair.first; } }; namespace boost { template <class T> struct result_of<select1st(T&)> { typedef P::first_type& type; }; template <class T> struct result_of<select1st(T const&)> { typedef P::first_type const& type; }; } transform_iterator<select1st, iter>
This works fine so long as BaseIterator::value_type is not const, but falls over when it is because I've defined the 'super_t::reference' type to be mutable.
I guess that I need a piece of metafunction magic, but my naive implementation fails
typename boost::mpl::apply_if< boost::is_const<typename BaseIterator::value_type> , typename BaseIterator::value_type::first_type const & , typename BaseIterator::value_type::first_type & >::type
Try plain mpl::if_. apply_if invokes one of two nullary metafunctions, but a (const) int& is not a metafunction.
trial.C:38: error: no type named `type' in `struct boost::mpl::apply_if< boost::is_const<std::pair<int, std::string> >, const int&, int&>'
I must admit I'm a bit baffled. There plainly is a 'type' in the apply_if class template.
Nope: template <class C, class T, class F> struct apply_if : typename if<C,T,F>::type {};
Any pointers? I attach the code as I have it.
While I'm at it, is there not something in the MPL that will return the appropriate const-qualified reference for me?
What do you mean?
None of the header file names in boost/mpl jump out and grab me, but I may well be looking in the wrong place.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
Why struggle?
boost::transform_iterator should give you just what you need:
Many thanks, David. That's altogether much nicer. However, result_of is not part of boost 1.31. Attached is an implementation of my code that works fine with 1.31. Unfortunately, I can't create a 'const_first_iterator' from a 'first_iterator'. Ie, I need: store my_store; store const & my_const_store = my_store; // UGLY! store::const_first_iterator const begin = my_const_store.begin_first(); store::const_first_iterator const end = my_const_store.end_first(); Any further clues, or is this as far as I can go this way? Angus

Angus Leeming <angus.leeming@btopenworld.com> writes:
David Abrahams wrote:
Why struggle?
boost::transform_iterator should give you just what you need:
Many thanks, David.
That's altogether much nicer. However, result_of is not part of boost 1.31. Attached is an implementation of my code that works fine with 1.31. Unfortunately, I can't create a 'const_first_iterator' from a 'first_iterator'. Ie, I need:
store my_store; store const & my_const_store = my_store; // UGLY! store::const_first_iterator const begin = my_const_store.begin_first(); store::const_first_iterator const end = my_const_store.end_first();
Any further clues, or is this as far as I can go this way?
See the converting constructor described at http://tinyurl.com/229ld#transform-iterator-synopsis. As long as the underlying iterators and unaryfunctions are convertible, the initialization should work just fine.
Angus
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
Any further clues, or is this as far as I can go this way?
See the converting constructor described at http://tinyurl.com/229ld#transform-iterator-synopsis. As long as the underlying iterators and unaryfunctions are convertible, the initialization should work just fine.
Thanks for the pointer. (Although I do read the docs before I post.) Kind regards, Angus
participants (2)
-
Angus Leeming
-
David Abrahams