Boost logo

Boost Users :

From: Roman Perepelitsa (romka_at_[hidden])
Date: 2006-08-14 08:21:11


Manfred Doudar <manfred.doudar <at> rsise.anu.edu.au> writes:

> Thank you kindly Roman, that helped - and is obvious now that I see it,
> again many thanks.
>
> I do however have one more boost::bind question that I can't quite get
> myself around.
>
> I want replace the following for-loop with a call to std::for_each, and
> am near certain that bind would do it:
>
> std::list<boost::tuple<int, float, std::string> > li;
>
> ...
>
> for (std::list<boost::tuple<int, float, std::string> >::iterator it =
> li.begin(); it != li.end(); ++it)
> {
> // this is ok - is all part of a class that inherits from MyFunctor
>
> MyFunctor::operator()(boost::get<0> (*it));
> }
>
> How might I convert the above to something using std::for_each, and
> boost::bind?
>
> Again, with thanks in advance

Hi.

It is almost imposible to explicitly bind boost::get because it's an
overloaded name with huge signature. The best thing you can do is to write
your own functor which can deduce tuple element type. Here is how you do it.

#include <list>
#include <algorithm>
#include <iostream>

#include <boost/lambda/bind.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>

using namespace boost;
using namespace boost::lambda;
using namespace std;

template <int N>
struct tuple_get
{
        template <class T>
        struct sig
        {
                typedef typename tuples::element<
                        N,
                        typename tuples::element<1, T>::type
>::type ret;

                typedef typename mpl::if_<
                        is_const<typename tuples::element<1, T>::type>,
                        typename tuples::access_traits<ret>::const_type,
                        typename tuples::access_traits<ret>::non_const_type
>::type type;
        };

        template <class T>
        typename sig<tuple<tuple_get, const T> >::type
        operator()(const T & t) const
        {
                return t.template get<N>();
        }

        template <class T>
        typename sig<tuple<tuple_get, T> >::type
        operator()(T & t) const
        {
                return t.template get<N>();
        }
};

void print(int i) { cout << i << endl; }

int main()
{
        typedef boost::tuple<int, float, std::string> data;
        typedef list<data> data_list;
        data_list li;

        std::for_each(
                li.begin(),
                li.end(),
                bind(print, bind(tuple_get<0>(), _1)));
}

This code uses boost::lambda::bind instead of boost::bind because I don't know
how to specify return type for functor in terms of boost::bind. 'typedef ...
result_type' is not enough here because return type depends of argument type.
Check boost::bind documentation if you want to use it instead of
boost::lambda::bind.

Roman Perepelitsa.


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