Boost logo

Boost :

Subject: Re: [boost] boost::bind result type
From: David Sankel (camior_at_[hidden])
Date: 2010-07-20 10:45:52


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!

David

-- 
David Sankel
Sankel Software
www.sankelsoftware.com
585 617 4748 (Office)

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