|
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