Boost logo

Boost :

Subject: Re: [boost] boost::bind result type
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-07-20 11:06:38


On Tue, Jul 20, 2010 at 10:45 AM, David Sankel <camior_at_[hidden]> wrote:
> On Mon, Jul 19, 2010 at 6:42 PM, Daniel Walker <daniel.j.walker_at_[hidden]>wrote:
>
>> On Mon, Jul 19, 2010 at 5:37 PM, David Sankel <camior_at_[hidden]> wrote:
>> > I'm wondering if there's a way I can generically get the result type of
>> > boost bind.
>> >
>> > I'd like to write something along these lines:
>> >
>> > template< typename StreamT, typename Sink >
>> > typename boost::result_of< boost::Bind( StreamT, boost::arg<1>, Sink )
>> >>::type
>> > apSink( StreamT t, Sink sk )
>> > {
>> >    return boost::bind( t
>> >                      , _1
>> >                      , sk
>> >                      );
>> > }
>> >
>> > I'm not interested in a boost::function solution because I require that
>> uses
>> > apSink's result can be inlined. Any ideas? Perhaps one of these other
>> > bind-like libraries has an answer to this.
>>
>> To my knowledge there is no general way to declare the return type of
>> boost::bind (or a Boost Lambda expression). In C++03 the best we can
>> do is boost::function, which can store arbitrary function objects
>> without having to know the type.
>
>
> Thanks Daniel. I have found a way do, somewhat awkwardly, what I want in
> C++03 so I'll give my solution below.
>
> Look at the header bind.hpp in the section commented "generic function
> objects", the return types are shown to be of the form:
>
> _bi::bind_t< R
>           , F
>           , typename _bi::list_av_1<A1>::type
>           >
> Where R is either the Z in a bind<Z> form or _bi::unspecified for the more
> common form. The list of arguments are part of the third template parameter.
> So my function then becomes:
>
> template< typename StreamT, typename Sink >
> boost::_bi::bind_t< boost::_bi::unspecified
>                  , StreamT
>                  , typename boost::_bi::list_av_2< Sink
>                                                  , boost::arg<1>
>                                                  >::type
>                  >
> apSink( StreamT t, Sink sk )
> {
>    return boost::bind( t
>                      , sk
>                      , _1
>                      );
> }
>
>
> However, this is really bad form as is anytime when passing an instance of
> bind_t to an outside function. The reason is that bind_t doesn't have normal
> callable semantics if it is used within another call to bind. To fix this
> problem boost::protect must be used. The following is the final version of
> my function:
>
> template< typename StreamT, typename Sink >
> boost::_bi::protected_bind_t<
>    boost::_bi::bind_t< boost::_bi::unspecified
>                      , StreamT
>                      , typename boost::_bi::list_av_2< Sink
>                                                      , boost::arg<1>
>                                                      >::type
>                      >
>    >
> apSink( StreamT t, Sink sk )
> {
>    return boost::protect( boost::bind( t
>                                      , sk
>                                      , _1
>                                      )
>                         );
> }
>
>
> Works great!

But this is not a generic solution. It is a very specific solution
that relies on internal types and implementation details of
boost::bind. It may not work for all releases of boost::bind and may
not work with other bind implementations.

Daniel Walker


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