
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. Thanks, David -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

On Mon, Jul 19, 2010 at 5:37 PM, David Sankel <camior@gmail.com> 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. In C++0x, the compiler can deduce the type so that you don't have to declare it. template< typename StreamT, typename Sink > auto apSink( StreamT t, Sink sk ) -> decltype(boost::bind(t, _1, sk)) { return boost::bind( t , _1 , sk ); } Hope that helps. Daniel Walker

On Mon, Jul 19, 2010 at 6:42 PM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
On Mon, Jul 19, 2010 at 5:37 PM, David Sankel <camior@gmail.com> 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)

On Tue, Jul 20, 2010 at 10:45 AM, David Sankel <camior@gmail.com> wrote:
On Mon, Jul 19, 2010 at 6:42 PM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
On Mon, Jul 19, 2010 at 5:37 PM, David Sankel <camior@gmail.com> 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

On Tue, Jul 20, 2010 at 11:06 AM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
On Tue, Jul 20, 2010 at 10:45 AM, David Sankel <camior@gmail.com> wrote:
On Mon, Jul 19, 2010 at 6:42 PM, Daniel Walker < daniel.j.walker@gmail.com>wrote:
On Mon, Jul 19, 2010 at 5:37 PM, David Sankel <camior@gmail.com> wrote:
I'm wondering if there's a way I can generically get the result type of boost bind. 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.
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.
Thanks for clarifying what I meant by awkward. Is it possible, and if so how, to make a generic solution? The main problem I see is bind taking a type argument in some cases. Could boost.bind be modified to expose a result type? I haven't seen any reasons yet for bind not including this really useful feature. David -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

AMDG David Sankel wrote:
Thanks for clarifying what I meant by awkward. Is it possible, and if so how, to make a generic solution? The main problem I see is bind taking a type argument in some cases. Could boost.bind be modified to expose a result type? I haven't seen any reasons yet for bind not including this really useful feature.
I believe that there's an open feature request for Boost.Typeof emulation support for Boost.Bind. If you're willing to live with your code only working on gcc, msvc, and any other compilers that have a built-in typeof or decltype, then you can use Boost.Typeof in native mode now. In Christ, Steven Watanabe

On Tue, Jul 20, 2010 at 12:09 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
David Sankel wrote:
Thanks for clarifying what I meant by awkward. Is it possible, and if so how, to make a generic solution? The main problem I see is bind taking a type argument in some cases. Could boost.bind be modified to expose a result type? I haven't seen any reasons yet for bind not including this really useful feature.
I believe that there's an open feature request for Boost.Typeof emulation support for Boost.Bind. If you're willing to live with your code only working on gcc, msvc, and any other compilers that have a built-in typeof or decltype, then you can use Boost.Typeof in native mode now.
That's a good idea. That would help bridge the C++03/0x gap. Here's another idea that we might be able to pursue in the future. The original complaint is not that there isn't a general way to return a bind object; you can use boost::function. The complaint is that boost::function isn't optimal, since it precludes inlining. So, another approach would be to provide an optimized specialization of boost::function for bind objects; i.e. boost::function could leverage implementation specific details of boost::bind to store bind objects optimally. It makes sense that Boost libraries would be optimized when used with other Boost libraries, and presumably, stdlib venders will look for similar opportunities for internal optimization in order to differentiate themselves. I'm not sure if this is possible, but it might be something worth looking into. Daniel Walker

AMDG Daniel Walker wrote:
Here's another idea that we might be able to pursue in the future. The original complaint is not that there isn't a general way to return a bind object; you can use boost::function. The complaint is that boost::function isn't optimal, since it precludes inlining. So, another approach would be to provide an optimized specialization of boost::function for bind objects; i.e. boost::function could leverage implementation specific details of boost::bind to store bind objects optimally. It makes sense that Boost libraries would be optimized when used with other Boost libraries, and presumably, stdlib venders will look for similar opportunities for internal optimization in order to differentiate themselves. I'm not sure if this is possible, but it might be something worth looking into.
This isn't possible without knowing the static type of the bind object. Boost.Function can't possibly avoid type erasure, so I don't think this leads anywhere. In Christ, Steven Watanabe

On Tue, Jul 20, 2010 at 1:09 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Daniel Walker wrote:
Here's another idea that we might be able to pursue in the future. The original complaint is not that there isn't a general way to return a bind object; you can use boost::function. The complaint is that boost::function isn't optimal, since it precludes inlining. So, another approach would be to provide an optimized specialization of boost::function for bind objects; i.e. boost::function could leverage implementation specific details of boost::bind to store bind objects optimally. It makes sense that Boost libraries would be optimized when used with other Boost libraries, and presumably, stdlib venders will look for similar opportunities for internal optimization in order to differentiate themselves. I'm not sure if this is possible, but it might be something worth looking into.
This isn't possible without knowing the static type of the bind object.
True, but the type of the bind object is not specified in the API. So, if we were to optimize boost::function and boost::bind to play well together, we could refactor the bind object type to suit our needs. I'm not saying it would be easy...
Boost.Function can't possibly avoid type erasure, so I don't think this leads anywhere.
You can't avoid type erasure when storing arbitrary types, but again, the return type of bind is implementation specific. Implementers of std::function and std::bind have have some flexibility in choosing the return type. There could be opportunities for Boost here too. Under certain assumptions, the return type of bind could even be an instance of boost::function. I'm more concerned about preserving the current semantics of boost::function, but perhaps they could be extended in an acceptable way. Sorry for being so imprecise. Just trying to think outside the box a little. :) Daniel Walker

On Tue, Jul 20, 2010 at 5:23 PM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On Tue, Jul 20, 2010 at 1:09 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Daniel Walker wrote:
Here's another idea that we might be able to pursue in the future. The original complaint is not that there isn't a general way to return a bind object; you can use boost::function. The complaint is that boost::function isn't optimal, since it precludes inlining. So, another approach would be to provide an optimized specialization of boost::function for bind objects; i.e. boost::function could leverage implementation specific details of boost::bind to store bind objects optimally. It makes sense that Boost libraries would be optimized when used with other Boost libraries, and presumably, stdlib venders will look for similar opportunities for internal optimization in order to differentiate themselves. I'm not sure if this is possible, but it might be something worth looking into.
This isn't possible without knowing the static type of the bind object.
True, but the type of the bind object is not specified in the API. So, if we were to optimize boost::function and boost::bind to play well together, we could refactor the bind object type to suit our needs. I'm not saying it would be easy...
Boost.Function can't possibly avoid type erasure, so I don't think this leads anywhere.
You can't avoid type erasure when storing arbitrary types, but again, the return type of bind is implementation specific. Implementers of std::function and std::bind have have some flexibility in choosing the return type. There could be opportunities for Boost here too. Under certain assumptions, the return type of bind could even be an instance of boost::function. I'm more concerned about preserving the current semantics of boost::function, but perhaps they could be extended in an acceptable way.
Sorry for being so imprecise. Just trying to think outside the box a little. :)
Actually, I just looked into it, and this wasn't as hard as I thought. So, I can be a little more specific about the needed changes. As a proof of concept, I have attached a patch that allows the following where the bind object is stored directly by boost::function without type erasure. #include <functional> #include <boost/function.hpp> #include <boost/bind.hpp> int main() { using namespace boost; function< bind_signature(std::plus<int>,boost::arg<1>,int) > f = bind(std::plus<int>(), _1, 1); } The tag "bind_signature" is used to specify that the signature has alternative semantics and should be interpreted to construct a boost::function instance optimized for storing a bind object. One could think of other conventions for specifying alternate boost::function semantics; e.g. function<bind_signature<std::plus<int>(boost::arg<1>,int)> > The point is to have some convention for the user to tell boost::function to interpret the signature differently, and then provide optimized specialization of the boost::function class template. The patch is far from complete and only works for two argument binds, but you get the idea. I basically just adapted David's return type solution and made it a member type of boost::function. Thanks David! I'm sure there are a number of nuances to be considered but basically to complete the feature: 1) decide on a signature convention 2) add support for multiple arities 3) define call operators for stored boost::bind objects 4) test and document everything Daniel Walker

AMDG Daniel Walker wrote:
Actually, I just looked into it, and this wasn't as hard as I thought. So, I can be a little more specific about the needed changes. As a proof of concept, I have attached a patch that allows the following where the bind object is stored directly by boost::function without type erasure.
#include <functional> #include <boost/function.hpp> #include <boost/bind.hpp>
int main() { using namespace boost; function< bind_signature(std::plus<int>,boost::arg<1>,int) > f = bind(std::plus<int>(), _1, 1); }
If you're going to specify all the parameters of the bind expression in the type of the boost::function, you'd be better off just having a metafunction for deducing the return type of bind. In Christ, Steven Watanabe

On Tue, Jul 20, 2010 at 8:16 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Daniel Walker wrote:
Actually, I just looked into it, and this wasn't as hard as I thought. So, I can be a little more specific about the needed changes. As a proof of concept, I have attached a patch that allows the following where the bind object is stored directly by boost::function without type erasure.
#include <functional> #include <boost/function.hpp> #include <boost/bind.hpp>
int main() { using namespace boost; function< bind_signature(std::plus<int>,boost::arg<1>,int) > f = bind(std::plus<int>(), _1, 1); }
If you're going to specify all the parameters of the bind expression in the type of the boost::function, you'd be better off just having a metafunction for deducing the return type of bind.
Yep, that would work too. I'm just trying to show that boost::function could be extended to store bind objects without the type erasure overhead. Daniel Walker

On Jul 20, 2010, at 7:43 PM, Daniel Walker wrote:
The patch is far from complete and only works for two argument binds, but you get the idea. I basically just adapted David's return type solution and made it a member type of boost::function. Thanks David!
Once you have that, why bother with function<>? -- David Abrahams BoostPro Computing http://boostpro.com

On Tue, Jul 20, 2010 at 8:46 PM, David Abrahams <dave@boostpro.com> wrote:
On Jul 20, 2010, at 7:43 PM, Daniel Walker wrote:
The patch is far from complete and only works for two argument binds, but you get the idea. I basically just adapted David's return type solution and made it a member type of boost::function. Thanks David!
Once you have that, why bother with function<>?
I suppose there's some stylistic appeal to having a single, common tool for storing functions. Less to learn and remember, maybe, easier maintenance: e.g. once you see "function<>" in someone else's code, you know what it's doing without having to look in a manuel, a single grep for "function" can retrieve all the stored function objects in a project, etc. Of course, another question is, once you have auto, why bother with function<>? But function<> could still be useful for a long time during the transition to the next standard and for maintaining legacy code. In that respect, extending function<> to handle more of the use cases of auto could also be helpful. Daniel Walker

Hi David, On 7/19/2010 10:37 PM, David Sankel wrote:
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 ); }
According to the bind docs, if StreamT is a function object, it needs to have a result_type to be compatible with bind. If StreamT is a function or member function you can use the function_types::result_type<> meta-function. So could you not write a meta-function that asks if its parameter is a function (once any pointer and reference baggage has been removed) and if so, use function_types::result_type<>, else just use the result_type member which has to be there anyway? Something like this: // entirely untested template<typename F> struct functor_result_type { typedef typename F::result_type type; }; template<typename F> struct strip_function : remove_pointer<typename remove_reference<F>::type> { }; template<typename F> struct bindable_result_type : mpl::eval_if < is_function<typename strip_function<F>::type>, function_types::result_type<F>, functor_result_type<F> > { }; Then: template<typename StreamT, typename Sink> typename bindable_result_type<StreamT>::type apSink(StreamT t, Sink sk) { return boost::bind(t, _1, sk); } Any good? Kind regards, Edd
participants (5)
-
Daniel Walker
-
David Abrahams
-
David Sankel
-
Edd Dawson
-
Steven Watanabe