Boost logo

Boost :

Subject: Re: [boost] [Bind] How do I get bind to deduce the return type offor_each?
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2010-04-16 21:36:36


On Fri, Apr 16, 2010 at 2:33 PM, Daniel Walker
<daniel.j.walker_at_[hidden]> wrote:
> On Fri, Apr 16, 2010 at 3:48 PM, Peter Dimov <pdimov_at_[hidden]> wrote:
>> Thomas Jordan wrote:
>>>
>>> Thanks a lot for the suggestion, I did take a look at Lambda library, and
>>> I saw that it used some extra type information in its STL
>>> algorithm wrappers (the 'sig') to help it figure out the return types.
>>> However, I am against using the Lambda library
>>> for other reasons, I only want to use the bind library.  I'd appreciate
>>> some specific advice on how to get the type deduction
>>> with the Boost.bind library.  Or is this just not possible with
>>> Boost.bind?
>>
>> It's not. Boost.Bind only supports function objects with a specific, fixed
>> type. There is no mechanism to tell it that the return type of
>>
>> struct myForEach
>> {
>>  template <typename II, typename F>
>>  F operator()(II begin, II end, F function) const
>>  {
>>     return std::for_each(begin, end, function);
>>  }
>> };
>>
>> is the same as its third argument. In this specific case I'd just use
>>
>> struct myForEach
>> {
>>  typedef void result_type;
>>  template <typename II, typename F>
>>  void operator()(II begin, II end, F function) const
>>  {
>>     std::for_each(begin, end, function);
>>  }
>> };
>
> That should work fine, but I was just playing around with this as
> well, so I'll just share some alternatives to consider.
>
> It seems Thomas wants to iterate over the objects in a
> multidimensional vector while calling a member function on each one.
> Before getting to boost bind, first, let's consider boost lambda,
> which has special facilities for embedded STL algorithms. For example,
> the following iterates over a 2x2 matrix containing objects of type S
> and calls S::f() on each one.
>
> #include <algorithm>
> #include <vector>
> #include <boost/lambda/algorithm.hpp>
> #include <boost/lambda/bind.hpp>
> #include <boost/range.hpp>
> using namespace boost;
>
> struct S
> {
>    int f() const {return 0;}
> };
>
> int main()
> {
>    typedef std::vector<S> vector_type;
>    typedef std::vector<vector_type> matrix_type;
>    matrix_type a(2, vector_type(2));
>
>    { using namespace boost::lambda;
>      std::for_each(a.begin(), a.end(),
>          bind(lambda::ll::for_each(),
>               bind(begin<const vector_type>, _1),
>               bind(end<const vector_type>, _1),
>               protect(bind(&S::f, _1))
>          )
>      );
>    }
> }
>
> This is adapted from the example code (http://tinyurl.com/y7jhu8t) in
> the lambda documentation. However, the same code can work using
> boost::bind if you change the block with the for_each call to
>
>    {
>      std::for_each(a.begin(), a.end(),
>          bind<void>(lambda::ll::for_each(),
>               bind(begin<const vector_type>, _1),
>               bind(end<const vector_type>, _1),
>               protect(bind(&S::f, _1))
>          )
>      );
>    }
>
> Note the bind<void>. This overrides bind's type deduction, which
> doesn't matter in this case, since the result of for_each is ignored
> anyway. Now, if you needed the result, to my knowledge, TR1 bind can
> handle argument dependent return types via result_of. However, boost
> lambda doesn't currently support the TR1 result_of protocol. See Trac
> ticket 864. So, you would still need to roll your own for_each functor
> with TR1 bind.

Do note, Boost.Phoenix supports that style just fine, and the code
would be even more simple yet if you used Phoenix instead of Lambda as
Phoenix is a complete and more powerful replacement for Lambda.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk