[utility] result_of and lambda patch

Hello, I noticed that result_of doesn't handle functors created by the Boost Lambda Library. For example, $ g++ -dumpversion 4.1.2 $ cat result_of_error.cpp #include <boost/lambda/lambda.hpp> #include <boost/utility/result_of.hpp> using namespace boost; template<class Functor, class Arg1, class Arg2> void f(Functor const&, Arg1 const&, Arg2 const&) { typedef typename result_of< Functor(Arg1, Arg2) >::type result_type; } int main() { using namespace lambda; int x = 0, y = 0; f(ret<int>(_1 + _2), x, y); } $ g++ -I./boost result_of_error.cpp 2>&1 | perl gSTLFilt.pl ./boost/boost/utility/result_of.hpp:68: error: no class template named 'result' in 'class boost::lambda::lambda_functor< ... >' ... $ Among Boost libraries, there are at least two ways for function objects to expose return types that are dependent on the types of their arguments. 1) result_of instructs users to expose a template result<F(ARG1, ..., ARGN)>. 2) Boost.Lambda instructs users to expose a template sig<tuple<ARG1, ..., ARGN>, and it also uses this convention internally. It might be nice to unify these two approaches one day or perhaps simplify the matter by implementing result_of in terms of the Boost Typeof Library along the lines of Douglas Gregor's "Looking Ahead" section in his 2003 paper, http://tinyurl.com/2nf5ym. But I figure in the mean time why not have result_of support both of the current approaches? If the functor has a nested sig template use that, otherwise try to use a nested result template. There's one additional caveat for supporting lambda expressions. A zero arity lambda functor expose its result type through the typedef nullary_return_type. This can be handle in result_of by providing a partial specialization of result_of_void_impl for the template class lambda::lambda_functor. The attached patch adds support for sig in functors and nullary lambda functors. Apply with 'patch -p0 < djw_result_of.patch' from the boost root directory. It depends on the has_template_xxx patch I submitted previously (http://tinyurl.com/35x5z5). Also, if has_template_xxx is unsupported for a particular compiler the patch supplies a partial specialization of result_of_nested_result for lambda::lambda_functor. That way at least lambda expressions can be supported if not user defined functors that employ the Boost Lambda Library's convention of specifying result types. I ran the Boost Utility Library test suite and everthing passed. Let me know and I can provide documentation and tests. Thanks! Daniel Walker

On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
Hello,
I noticed that result_of doesn't handle functors created by the Boost Lambda Library. [...] Among Boost libraries, there are at least two ways for function objects to expose return types that are dependent on the types of their arguments.
1) result_of instructs users to expose a template result<F(ARG1, ..., ARGN)>. 2) Boost.Lambda instructs users to expose a template sig<tuple<ARG1, ..., ARGN>, and it also uses this convention internally.
One more: 3) Fusion instruct users to expose a template result<ARG1... ARGN>. But I guess it is not easy to distinguish this case from 1). gpd

On 3/20/07, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
Hello,
I noticed that result_of doesn't handle functors created by the Boost Lambda Library. [...] Among Boost libraries, there are at least two ways for function objects to expose return types that are dependent on the types of their arguments.
1) result_of instructs users to expose a template result<F(ARG1, ..., ARGN)>. 2) Boost.Lambda instructs users to expose a template sig<tuple<ARG1, ..., ARGN>, and it also uses this convention internally.
One more:
3) Fusion instruct users to expose a template result<ARG1... ARGN>.
But I guess it is not easy to distinguish this case from 1).
Thanks. I wasn't aware of this case. I was afraid there may be other conventions out there. I believe Boost.Typeof would handle the Fusion case as well as any future conventions adopted by future libraries. Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof. Daniel

Daniel Walker wrote:
Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
IMO, you have this backwards. Rather than patch result_of to handle lambda, lambda function objects should be modified to follow the result_of convention. It's now standard, after all. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
IMO, you have this backwards. Rather than patch result_of to handle lambda, lambda function objects should be modified to follow the result_of convention. It's now standard, after all.
Good point. I considered doing that, but didn't want to intrude on any user code out there that follows the current Boost.Lamda convention. Of course, I don't mind submitting a patch to Boost.Lambda as you suggest if there's interest. That would help alleviate the problem of having multiple return type conventions among Boost libraries. I could also try to patch Fusion. Perhaps, my result_of patch could still be useful for providing backwards compatibility for current Boost.Lambda style user defined functors. Daniel

Daniel Walker wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
IMO, you have this backwards. Rather than patch result_of to handle lambda, lambda function objects should be modified to follow the result_of convention. It's now standard, after all.
Good point. I considered doing that, but didn't want to intrude on any user code out there that follows the current Boost.Lamda convention. Of course, I don't mind submitting a patch to Boost.Lambda as you suggest if there's interest. That would help alleviate the problem of having multiple return type conventions among Boost libraries. I could also try to patch Fusion. Perhaps, my result_of patch could still be useful for providing backwards compatibility for current Boost.Lambda style user defined functors.
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
IMO, you have this backwards. Rather than patch result_of to handle lambda, lambda function objects should be modified to follow the result_of convention. It's now standard, after all.
Good point. I considered doing that, but didn't want to intrude on any user code out there that follows the current Boost.Lamda convention. Of course, I don't mind submitting a patch to Boost.Lambda as you suggest if there's interest. That would help alleviate the problem of having multiple return type conventions among Boost libraries. I could also try to patch Fusion. Perhaps, my result_of patch could still be useful for providing backwards compatibility for current Boost.Lambda style user defined functors.
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems.
That's true, but I was concerned about funtors defined by lambda users. Currently, if a user wants to write a functor to be used in a lambda expression, the user needs to supply a sig<> to tell lambda what the functor's return type is. Of course, users currently can't use these functors with result_of anyway. So, I suppose no one's feelings will be hurt if result_of doesn't support their current lambda compatible functors. And it's not too imposing to demand that they modify their functors to conform to the result_of standard, so long as they can still be used in lambda expressions. I think I'll try to patch lambda. Thanks! Daniel

On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Daniel Walker wrote:
Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
IMO, you have this backwards. Rather than patch result_of to handle lambda, lambda function objects should be modified to follow the result_of convention. It's now standard, after all.
Good point. I considered doing that, but didn't want to intrude on any user code out there that follows the current Boost.Lamda convention. Of course, I don't mind submitting a patch to Boost.Lambda as you suggest if there's interest. That would help alleviate the problem of having multiple return type conventions among Boost libraries. I could also try to patch Fusion. Perhaps, my result_of patch could still be useful for providing backwards compatibility for current Boost.Lambda style user defined functors.
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems.
That's true, but I was concerned about funtors defined by lambda users. Currently, if a user wants to write a functor to be used in a lambda expression, the user needs to supply a sig<> to tell lambda what the functor's return type is.
Of course, users currently can't use these functors with result_of anyway. So, I suppose no one's feelings will be hurt if result_of doesn't support their current lambda compatible functors. And it's not too imposing to demand that they modify their functors to conform to the result_of standard, so long as they can still be used in lambda expressions. I think I'll try to patch lambda. Thanks!
What about doing both? Result_of would implement (maybe undocumented and deprecated) sig support. Lambda would implement and document both result and sig, deprecating the latter. In a release or two, both lambda and result_of would drop sig support. The users should have plenty of time for updating their code. gpd

On 3/20/07, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems.
That's true, but I was concerned about funtors defined by lambda users.
What about doing both? Result_of would implement (maybe undocumented and deprecated) sig support. Lambda would implement and document both result and sig, deprecating the latter. In a release or two, both lambda and result_of would drop sig support. The users should have plenty of time for updating their code.
That sounds like a good idea to me. I was just looking into adding result<> support to Lambda, and I think it's fairly strait forward. I came up with the following preprocessor metafunction to help things along, and I believe it could have a general use for folks writing result_of compatible functors. I'm not sure if it should be included in a library someplace, perhaps result_of. I imagine this would help Fusion provide support for result_of style result. // Expands to partial specializations of an argument dependent nested // result<> type generator for functors with variable arity. // first - the lower bound of the functor arity. // last - the upper bound of the functor arity. // macro - a unary operation of the form macro(n) where n is the // current arity of the function. This macro is used as the // definition of result<>::type like so: // typedef macro(n) type; BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE(first, last, macro) It would be easy to define another macro BOOST_FIXED_ARITY_FUNCTOR_RESULT_TYPE for when you don't want partial specializations of result<> for multiple numbers of arguments to the functor. The implementation looks like this. #define BOOST_RESULT_TYPE_PARTIAL_SPECIALIZATIONS(z, n, macro) \ template < \ class F \ BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) \ > \ struct result<F(BOOST_PP_ENUM_PARAMS(n, A))> { \ typedef macro(n) type; \ }; \ /**/ #define BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE(first, last, macro) \ template <class F> struct result; \ BOOST_PP_REPEAT_FROM_TO( \ first, last \ , BOOST_RESULT_TYPE_PARTIAL_SPECIALIZATIONS \ , macro \ ) \ /**/ Here's how I used it in lambda::lambda_functor<>. #define BOOST_LAMBDA_FUNCTOR_NULL_RESULT_TYPE(n) \ typename F::nullary_return_type \ /**/ #define BOOST_LAMBDA_FUNCTOR_NARY_RESULT_TYPE(n) \ typename sig<tuple<BOOST_PP_ENUM_PARAMS(n, A)> >::type \ /**/ #define BOOST_LAMBDA_FUNCTOR_RESULT_TYPE(n) \ BOOST_PP_IF( \ n \ , BOOST_LAMBDA_FUNCTOR_NARY_RESULT_TYPE \ , BOOST_LAMBDA_FUNCTOR_NULL_RESULT_TYPE \ )(n) \ /**/ BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE( 0 , BOOST_PP_INC(BOOST_RESULT_OF_NUM_ARGS) , BOOST_LAMBDA_FUNCTOR_RESULT_TYPE ) It expands to something like ... template <class F> struct result; template < class F > struct result<F()> { typedef typename F::nullary_return_type type; }; template < class F , class A0 > struct result<F( A0)> { typedef typename sig<tuple< A0> >::type type; }; template < class F , class A0 , class A1 > struct result<F( A0 , A1)> { typedef typename sig<tuple< A0 , A1> >::type type; }; When I submit the lambda patch, should I make this macro internal to the lambda library or expose it to the public in some other library? If it should be exposed where do you think a good home for it would be? Daniel

Giovanni Piero Deretta wrote:
On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems.
That's true, but I was concerned about funtors defined by lambda users. Currently, if a user wants to write a functor to be used in a lambda expression, the user needs to supply a sig<> to tell lambda what the functor's return type is.
Of course, users currently can't use these functors with result_of anyway. So, I suppose no one's feelings will be hurt if result_of doesn't support their current lambda compatible functors. And it's not too imposing to demand that they modify their functors to conform to the result_of standard, so long as they can still be used in lambda expressions. I think I'll try to patch lambda. Thanks!
What about doing both? Result_of would implement (maybe undocumented and deprecated) sig support. Lambda would implement and document both result and sig, deprecating the latter. In a release or two, both lambda and result_of would drop sig support. The users should have plenty of time for updating their code.
I'm not sure this is a good idea. I haven't looked at the patch to mpl's has_xxx code to make it detected nested class templates, but I wonder how portable it is to older compilers. I know from experience how finicky the result_of implementation is, and getting this to work on all the compilers result_of currently works on would be a difficult (impossible?) task. I'm willing to be proved wrong, however. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
Giovanni Piero Deretta wrote:
What about doing both? Result_of would implement (maybe undocumented and deprecated) sig support. Lambda would implement and document both result and sig, deprecating the latter. In a release or two, both lambda and result_of would drop sig support. The users should have plenty of time for updating their code.
I'm not sure this is a good idea. I haven't looked at the patch to mpl's has_xxx code to make it detected nested class templates, but I wonder how portable it is to older compilers. I know from experience how finicky the result_of implementation is, and getting this to work on all the compilers result_of currently works on would be a difficult (impossible?) task. I'm willing to be proved wrong, however.
You're right that detecting nested templates may not be portable to older compilers. However, my result_of patch doesn't require full nested template detection support. My patch for has_template_xxx (I didn't try to change has_xxx to support both nested classes and template classes) provides functionality on unsupported compilers the same way has_xxx does. has_template_xxx::value is always false on unsupported compilers (or a user supplied default). In my patch for result_of, lack of support for has_template_xxx is handled by checking BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX. In this case, partial specializations for lambda::lambda_functor are provided so that lambda expressions can be supported, even though user defined functors using sig<> cannot. result_of already requires that the compiler support partial specialization. So, to the best of my knowledge, this doesn't add an additional limitation on the number of compilers result_of can work on. Daniel

Daniel Walker wrote:
In my patch for result_of, lack of support for has_template_xxx is handled by checking BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX. In this case, partial specializations for lambda::lambda_functor are provided so that lambda expressions can be supported, even though user defined functors using sig<> cannot. result_of already requires that the compiler support partial specialization. So, to the best of my knowledge, this doesn't add an additional limitation on the number of compilers result_of can work on.
If 'result_of' customization way is not enough, why not introduce a customization point. template<typename F, typename FArgs, typename EnableIf> struct extend_result_of; Then, the customizations for lambda is placed at <boost/lambda/result_of.hpp>. That's generics. :-) Anyway I don't recommand to touch 'result_of' for now. IIRC, 'result_of' was born a few weeks ago; for VC++7.1/8 users. Before Mr.Niebler's patch, it had been broken for long years because of VC++ bugs. As I pointed, a lambda::functor doesn't need any patch. 'bind' turns a function using 'sig' into a lambda::functor. Thus, we have nearly everything without any patch. On the other hand, "result_of<lambda>" project will be an interesting work. What does "result_of<bind(..)>" return? I want to know it :-) Regards, -- Shunsuke Sogame

On 3/20/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
In my patch for result_of, lack of support for has_template_xxx is handled by checking BOOST_MPL_CFG_NO_HAS_TEMPLATE_XXX. In this case, partial specializations for lambda::lambda_functor are provided so that lambda expressions can be supported, even though user defined functors using sig<> cannot. result_of already requires that the compiler support partial specialization. So, to the best of my knowledge, this doesn't add an additional limitation on the number of compilers result_of can work on.
If 'result_of' customization way is not enough, why not introduce a customization point. template<typename F, typename FArgs, typename EnableIf> struct extend_result_of; Then, the customizations for lambda is placed at <boost/lambda/result_of.hpp>. That's generics. :-)
This isn't a bad idea, but I feel that result_of is a simple utility and doesn't merit an additional interface to provide for user extension. Users should simply provide result<>. Boost.Lambda is a special case partially because of long standing precedence and a large user base. It's been around for ages. I like Giovanni's suggestion for transitioning away from sig<> support. If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed.
As I pointed, a lambda::functor doesn't need any patch. 'bind' turns a function using 'sig' into a lambda::functor. Thus, we have nearly everything without any patch.
With lambda functors exposing result<> you're right that you can use lambda::bind to get the result_of::type of a function. However, this involves a slight change in semantics. lambda::bind delays the call of a functor, after all, which shouldn't be necessary to get the functors return type. For example (this requires my lambda patch here http://tinyurl.com/2jgtld) ... #include <boost/lambda/bind.hpp> #include <boost/tuple/tuple.hpp> #include <boost/utility/result_of.hpp> using namespace boost; struct functor { template<class Args> struct sig { typedef typename tuples::element<1, Args>::type type; }; template<class Arg> typename sig<tuple<functor, Arg> >::type operator()(Arg const& a) const { return a; } }; template<class F, class Arg> void g(F const& f, Arg& x) { typename result_of< F(F, Arg) >::type y = f(x); } int main() { using namespace boost::lambda; typedef char value_type; value_type x; functor f; // Call f right away. result_of< functor(functor, value_type) >::type y = f(x); // Delay call of f until later. g(bind(f, _1), x); } In the example above where functor f is lambda compatible according to the existing convention, calling f right away causes an error without the result_of patch even though delaying the call to f succeeds with the lambda patch.
On the other hand, "result_of<lambda>" project will be an interesting work. What does "result_of<bind(..)>" return? I want to know it :-)
This is kind of cool! First off, to literally use something like 'result_of<bind(functor)>::type' is illegal. Bind is not a constant expression. result_of requires a function/functor type. I believe Boost.Typeof can do this, though. But in answer to your question the following illustrates the type of result_of<>::type when applied to a lambda bound functor (this also requires my new lambda patch). #include <boost/lambda/bind.hpp> #include <boost/mpl/assert.hpp> #include <boost/type_traits.hpp> #include <boost/utility/result_of.hpp> using namespace boost; struct functor { BOOST_FIXED_ARITY_FUNCTOR_RESULT(2, A1) template<class Arg> typename result<functor(functor, Arg)>::type operator()(Arg const& a) const { return a; } }; template<class F, class BoundF, class Arg> void f(F const&, BoundF const&, Arg const&) { BOOST_MPL_ASSERT(( is_same< typename result_of<F(F, Arg)>::type , typename result_of<BoundF(BoundF, Arg)>::type > )); } int main() { using namespace lambda; typedef char value_type; value_type x; functor user_functor; f(user_functor, bind(user_functor, _1), x); } Note that if user_functor had used the existing lambda sig<> convention (as is currently the common case among Boost.Lambda users) this will not compile without the result_of patch. Daniel

Daniel Walker wrote:
This isn't a bad idea, but I feel that result_of is a simple utility and doesn't merit an additional interface to provide for user extension. Users should simply provide result<>. Boost.Lambda is a special case partially because of long standing precedence and a large user base. It's been around for ages. I like Giovanni's suggestion for transitioning away from sig<> support.
If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed.
It will break a code using not result_of but sig compatible functors? Apart from politics, I prefer "virtual" to "switch", :-) whether or not the "virtual"(that is, 'extend_result_of') is a public interface.
template<class F, class Arg> void g(F const& f, Arg& x) { typename result_of< F(F, Arg) >::type y = f(x); }
This usage of 'result_of' seems wrong. You meant? typename result_of< F(Arg&) >::type y = f(x);
In the example above where functor f is lambda compatible according to the existing convention, calling f right away causes an error without the result_of patch even though delaying the call to f succeeds with the lambda patch.
Can the patch support a sig compatible functor which is "nullary-callable" (e.g. lambda::constructor<>) ?
On the other hand, "result_of<lambda>" project will be an interesting work. What does "result_of<bind(..)>" return? I want to know it :-)
This is kind of cool! First off, to literally use something like 'result_of<bind(functor)>::type' is illegal. Bind is not a constant expression. result_of requires a function/functor type.
I really want the type, which can be used with result_of. Some considerations will be required.
struct functor { BOOST_FIXED_ARITY_FUNCTOR_RESULT(2, A1)
template<class Arg> typename result<functor(functor, Arg)>::type operator()(Arg const& a) const { return a; } };
I introduce <boost/detail/functionN.hpp> at Boost.Accumulators, which seems very cool. Regards, -- Shunsuke Sogame

On 3/21/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed.
It will break a code using not result_of but sig compatible functors?
Yes. That's the reason lambda would support both for a time with sig<> being deprecated. After a release or two (giving users plenty of time to update their code) sig<> would be removed. This gives them a fair warning and time to adapt.
template<class F, class Arg> void g(F const& f, Arg& x) { typename result_of< F(F, Arg) >::type y = f(x); }
This usage of 'result_of' seems wrong. You meant? typename result_of< F(Arg&) >::type y = f(x);
Thanks for pointing this out. You're right, this is incorrect. I thought this usage was awkward when I first saw it. I just thought it was cool that my lambda changes worked at all and that's largely due to the sound library design of Jaakko Järvi. I'll submit an explanation and a revised lambda patch on the thread where I posted the original.
Can the patch support a sig compatible functor which is "nullary-callable" (e.g. lambda::constructor<>) ?
Yes. I just tested it with lambda::constructor<>, and it does work.
result_of requires a function/functor type.
I really want the type, which can be used with result_of. Some considerations will be required.
Oh, I misunderstood. I thought you wanted the type that result_of generates. Everything regarding types that can be used with result_of is the same as the current result_of documentation with two exceptions. First, where the documentation says "F::result<F(T1, T2, ..., TN)>::type" add 'or F::sig<tuple<F, T1, T2, ..., TN> >::type'. Second, result_of accepts any functor generated by a lambda expression; specifically any type instantiated from lambda::lambda_functor<>. If/when lambda standardizes on result<> instead of sig<> you could remove both exceptions and revert the documentation back to it's current state.
struct functor { BOOST_FIXED_ARITY_FUNCTOR_RESULT(2, A1)
template<class Arg> typename result<functor(functor, Arg)>::type operator()(Arg const& a) const { return a; } };
I introduce <boost/detail/functionN.hpp> at Boost.Accumulators, which seems very cool.
I looked for your file in the boost-sandbox cvs repository and couldn't find it. Could you send a link? Thanks! Daniel

Daniel Walker wrote:
On 3/21/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed. It will break a code using not result_of but sig compatible functors?
Yes. That's the reason lambda would support both for a time with sig<> being deprecated. After a release or two (giving users plenty of time to update their code) sig<> would be removed. This gives them a fair warning and time to adapt.
I think users don't want to spend the time. Smart users will protect themselves right now by using something like.. struct sig_compatible_fun : enable_result_of_sig // added { // ... }; Hmm, patch is no longer required. :-)
Can the patch support a sig compatible functor which is "nullary-callable" (e.g. lambda::constructor<>) ?
Yes. I just tested it with lambda::constructor<>, and it does work.
I tried this: #include <boost/utility/result_of.hpp> #include <boost/lambda/construct.hpp> int main() { using boost::lambda::constructor; using boost::result_of; int i = 1; result_of<constructor<int>(int&)>::type r = constructor<int>()(i); // (1) GCC compiles. result_of<constructor<int>()>::type r = constructor<int>()(); // (2) GCC fails. } I guess a sig-compatible functor which is nullary-callable must be ported to result_of, even if the patch is applied. Note that nullary instantiation of 'result_of' must always succeed. (See the rationale at http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html) Well, I have bad news. VC++7.1 and VC8 can't compile (1) nor (2). :-(
I introduce <boost/detail/functionN.hpp> at Boost.Accumulators, which seems very cool.
I looked for your file in the boost-sandbox cvs repository and couldn't find it. Could you send a link?
See the accumulators.zip in "Math - Numerics" directory at Boost Vault. Regards, -- Shunsuke Sogame

On 3/22/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
On 3/21/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
If/when lambda standardizes on result<>, the lambda related special cases in result_of can be removed. It will break a code using not result_of but sig compatible functors?
Yes. That's the reason lambda would support both for a time with sig<> being deprecated. After a release or two (giving users plenty of time to update their code) sig<> would be removed. This gives them a fair warning and time to adapt.
I think users don't want to spend the time. Smart users will protect themselves right now by using something like..
struct sig_compatible_fun : enable_result_of_sig // added { // ... };
Hmm, patch is no longer required. :-)
There are lots of ways that users can work around the fact that result_of can't work with lambda. We've discussed several. There are usually ways for users to work around missing features and/or bugs in the 3rd party libraries they use. The point of my patches are to make result_of work with lambda without requiring additional user effort. I believe this is a reasonable expectation. I first ran into this problem because the Boost.Parameter library explicitly told users to use lambda and then passed the lambda functor to result_of. When it didn't work, it appeared like a bug in the parameter library. So, I think it is not an uncommon disappointment among boost users and developers that lambda and result_of don't play nicely together out of the box. Plus, as Eric pointed out earlier in this thread, the result_of convention of using result<> for return types is now standard (is that TR1?). Why shouldn't lambda follow it? An alternative might be to leave result_of unchanged but provide a converter along the lines of your suggestion: a function adapter that would make lambda expressions usable in result_of. Boost users could use this with lambda expressions and their own lambda compatible functors. Boost.Parameter could use it to make lazy binding work as advertised. However, in the long run it seems like there should be a single convention for specifying argument dependent return types using result<>, and user expectations such as boost libraries being interoperable should be met as much as possible.
Can the patch support a sig compatible functor which is "nullary-callable" (e.g. lambda::constructor<>) ?
Yes. I just tested it with lambda::constructor<>, and it does work.
I tried this:
#include <boost/utility/result_of.hpp> #include <boost/lambda/construct.hpp>
int main() { using boost::lambda::constructor; using boost::result_of;
int i = 1; result_of<constructor<int>(int&)>::type r = constructor<int>()(i); // (1) GCC compiles.
result_of<constructor<int>()>::type r = constructor<int>()(); // (2) GCC fails. }
I missed this. I tested with something like ... template<class F> void f(F const& f) { typename result_of< F() >::type y = f(); } int main() { using namespace lambda; f(bind(constructor<int>())); } ... which works due to the resul_ot patch, not the lambda patch. I'll explain. As I understand it, the problem here is two fold. First, the result_of documentation states that: "result_of<F(T1, T2, ..., TN)> is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0." So, any nullary result_of<F()> will be void unless F provides result_type. The same is true if F provides sig<>... with one exception: if F is generated from a lambda expression result_of<F()> will deduce the correct type. constructor<> isn't a lambda expression. It's a wrapper class that can be used as a target function of lambda::bind expressions. Second, I inadvertently made the type deduction in result_of more powerful for lambda expression than the usual functors. It can correctly deduce the return types of a lambda::lambda_functor taking zero or more arguments. result_of can not deduce the return types of any arbitrary functor F which overrides operator() for zero or more arguments due to the fact that when the number of arguments for F::result<F()> is zero result_of always evals to void. You can't supply a F::result_type for this case because it will be preferred over the F::result<> for the operator()s that take arguments. It seems to me that this limitation is simple to overcome if you make result_of dependent on whether the functor provides a result_type or result<> (or sig<>) instead of the number of arguments. The documentation would read something like the following. "When F is a class type with a member type result_type, result_of<F(T1, T2, ..., TN)> is F::result_type. Otherwise, if F is a class type with a member type F::result<F(T1, T2, ..., TN)>::type, result_of<F(T1, T2, ..., TN)>::type is F::result<F(T1, T2, ..., TN)>::type. Otherwise, result_of<F(T1, T2, ..., TN)>::type is void for N >= 0." The third case could be changed to be dependent on the number of arguments (after giving the user a chance to supply result_type or result<>) if that's preferable. This is simple to implement with has_template_xxx. Am I missing something? If it's impossible to make the above changes due to the fact that the behavior has already been standardized, I could instead provide specializations for result_of with nullary lambda expressions (and helper classes like construct) in the lambda library and get the same effect. This is what Douglas suggested for users to do in the rationale sited below.
I guess a sig-compatible functor which is nullary-callable must be ported to result_of, even if the patch is applied.
The same is true for a result-compatible functor as described above. This is an existing limitation of result_of which we may or may not want to address.
Note that nullary instantiation of 'result_of' must always succeed. (See the rationale at http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html)
I believe the errors you're seeing are due to the assignment to r (which is declared void) and not to result_of<constructor<int>()> being ill-formed.
Well, I have bad news. VC++7.1 and VC8 can't compile (1) nor (2). :-(
Could you send the error messages you're getting for (1)? (2) won't compile due to the limitation that result_of always ignores nullary F::result<F()>::type.
I introduce <boost/detail/functionN.hpp> at Boost.Accumulators, which seems very cool.
I looked for your file in the boost-sandbox cvs repository and couldn't find it. Could you send a link?
See the accumulators.zip in "Math - Numerics" directory at Boost Vault.
I'll check it out. Thanks again! Daniel

Daniel Walker wrote:
Plus, as Eric pointed out earlier in this thread, the result_of convention of using result<> for return types is now standard (is that TR1?). Why shouldn't lambda follow it?
As pointed, lambda should and can follow 'result_of' by using this way: http://tinyurl.com/2xw4s2 , which will be <boost/lambda/result_of.hpp> or something. Note that the nullary instantiation seems not special case.
The third case could be changed to be dependent on the number of arguments (after giving the user a chance to supply result_type or result<>) if that's preferable. This is simple to implement with has_template_xxx. Am I missing something?
As the rationale states, nullary intantiations of 'result_of' must always succeed even if the functions are never called. (Hence, it has the *default* result type -- 'void'.) Can has_template_xxx detect whether or not a sig-compatible functor is nullary-callable?
I guess a sig-compatible functor which is nullary-callable must be ported to result_of, even if the patch is applied.
The same is true for a result-compatible functor as described above. This is an existing limitation of result_of which we may or may not want to address.
If user workarounds of sig-compatible functor users cannot be removed, that patch loses the original intention?
Note that nullary instantiation of 'result_of' must always succeed. (See the rationale at http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html)
I believe the errors you're seeing are due to the assignment to r (which is declared void) and not to result_of<constructor<int>()> being ill-formed.
Yes.
Well, I have bad news. VC++7.1 and VC8 can't compile (1) nor (2). :-(
Could you send the error messages you're getting for (1)? (2) won't compile due to the limitation that result_of always ignores nullary F::result<F()>::type.
has_template_xxx seems not to work. I tried this: typedef char value_type; BOOST_MPL_ASSERT(( has_template_result< pair_maker, pair_maker(value_type, value_type) > )); This assertion fails under VC7.1/VC8. Regards, -- Shunsuke Sogame

On 3/22/07, shunsuke <pstade.mb@gmail.com> wrote:
Daniel Walker wrote:
Plus, as Eric pointed out earlier in this thread, the result_of convention of using result<> for return types is now standard (is that TR1?). Why shouldn't lambda follow it?
As pointed, lambda should and can follow 'result_of' by using this way: http://tinyurl.com/2xw4s2 , which will be <boost/lambda/result_of.hpp> or something. Note that the nullary instantiation seems not special case.
OK I think we're getting closer to a good solution. Your file has specializations for lambda::lambda_functor that work for lambda expressions, which is why the nullary instantiations work. My result_of patch also had a specialization for lambda::lambda_functor, which made the nullary case work. If lambda expressions provided the standard result<> (as Eric suggested and my lambda patch implements) only the specializations for the nullary case would be necessary (unless this special case were removed entirely from result_of using has_template_xxx). I would be perfectly happy using your <boost/lambda/result_of.hpp> for the nullary case alone, if we moved it to <boost/lambda/detail/result_of.hpp> and had the boost/lambda/* headers include it so that lambda/result_of interoperability was transparent to the user. That combined with the lambda patch would probably suffice. However, this doesn't take care of the case where the user would like to use a lambda compatible functor with result_of directly, as in calling a functor right away rather than delaying the call with lambda::bind per my previous example in this thread. It also doesn't take care of your example of calling lambda::construct<> directly without lambda::bind. To handle lambda::construct<> and the other lambda wrapper functors you could add nullary specialization of result_of to your file. We should also have the wrapper classes expose result<> so that they are more standard conformant. This will handle the nary result_of cases for lambda wrapper functors. To handle arbitrary user defined lambda compatible functors still requires adding sig<> support to result_of (or a function adapter that user's can use to convert their functors). Or we could just not handle this case. Users currently can't use these functors with result_of anyway. So, I suppose no one's feelings will be hurt if result_of doesn't support their current lambda compatible functors. Besides, when they upgrade to the result<> standard that lambda accepts with my patch, they get result_of compatibility as a bonus. If we don't handle user defined lambda compatible functors I see no need to patch result_of at all, which I think would make everyone happy. This is beginning to sound like a good approach to me.
The third case could be changed to be dependent on the number of arguments (after giving the user a chance to supply result_type or result<>) if that's preferable. This is simple to implement with has_template_xxx. Am I missing something?
As the rationale states, nullary intantiations of 'result_of' must always succeed even if the functions are never called. (Hence, it has the *default* result type -- 'void'.) Can has_template_xxx detect whether or not a sig-compatible functor is nullary-callable?
Yes. With my patch nullary instantiations of result_of are succeeding: result_of<F()>::type is void. The problem as far as I can tell is that result_of is choosing the default void rather than correctly deducing the actual return type as given by F::result<F()>::type or F::sig<tuple<F> >::type. But this has always been a limitation of result_of. The way to get around it is by specializing result_of for nullary F. I believe has_template_xxx could take away this limitation by only choosing the default type void when the functor doesn't have F::result<F()>.
I guess a sig-compatible functor which is nullary-callable must be ported to result_of, even if the patch is applied.
The same is true for a result-compatible functor as described above. This is an existing limitation of result_of which we may or may not want to address.
If user workarounds of sig-compatible functor users cannot be removed, that patch loses the original intention?
I'm not sure if I fully understand your question, but the patch doesn't lose the original intent entirely. Users can still use nary sig-compatible functors, which they couldn't use before. (However, as I stated above, it would be convenient but I'm not sure that it's necessary for result_of to support the current sig convention.) Lambda users are in the same boat as people writing result-compatible functors when it comes to nullary calls. They need to write a specialization of result_of for when their functor is called with no arguments. result_of doesn't attempt to automatically deduce the type, although it could with has_template_xxx.
has_template_xxx seems not to work. I tried this:
typedef char value_type; BOOST_MPL_ASSERT(( has_template_result< pair_maker, pair_maker(value_type, value_type) > ));
This assertion fails under VC7.1/VC8.
That's expected. Someone needs to cover the compiler workarounds that has_xxx includes, and I'm not sure if I can do that right away. I may give it a shot. Note that result_of still works on VC7.1 and VC8, but the new functionality is not be available. Daniel

Daniel Walker wrote:
I would be perfectly happy using your <boost/lambda/result_of.hpp> for the nullary case alone, if we moved it to <boost/lambda/detail/result_of.hpp> and had the boost/lambda/* headers include it so that lambda/result_of interoperability was transparent to the user. That combined with the lambda patch would probably suffice.
I don't recommand the way to include implicitly. It would actually break codes written by the author of http://tinyurl.com/2xw4s2 , which is not mine. IMO, it should be separated, following Boost.Typeof way.
If user workarounds of sig-compatible functor users cannot be removed, that patch loses the original intention?
I'm not sure if I fully understand your question, but the patch doesn't lose the original intent entirely. Users can still use nary sig-compatible functors, which they couldn't use before. (However, as I stated above, it would be convenient but I'm not sure that it's necessary for result_of to support the current sig convention.) Lambda users are in the same boat as people writing result-compatible functors when it comes to nullary calls. They need to write a specialization of result_of for when their functor is called with no arguments. result_of doesn't attempt to automatically deduce the type, although it could with has_template_xxx.
After all, this seems to depend on the functionality and portability of has_template_xxx. I hope it will work under VC++. Regards, -- Shunsuke Sogame

"Daniel Walker" <daniel.j.walker@gmail.com> wrote
I believe Boost.Typeof would handle the Fusion case as well as any future conventions adopted by future libraries. Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
Please note that typeof strips top-level references, and therefore its usage in relation to result_of is very limited and may not give the correct result unless you are sure that the result is not a reference. Regards, Arkadiy

On Tue, 2007-03-20 at 15:55 -0400, Arkadiy Vertleyb wrote:
"Daniel Walker" <daniel.j.walker@gmail.com> wrote
I believe Boost.Typeof would handle the Fusion case as well as any future conventions adopted by future libraries. Still, for compilers that Boost.Typeof doesn't support, it would be nice if result_of could handle Boost.Lambda at least. More recent libraries and future libraries could consider adopting a previously existing practice (result<F(Args) or sig<tuple<Args> >) that result_of can support without typeof.
Please note that typeof strips top-level references, and therefore its usage in relation to result_of is very limited and may not give the correct result unless you are sure that the result is not a reference.
Once decltype starts trickling into compilers, the Typeof library can start using it. For example, ConceptGCC already supports decltype... Cheers, Doug

Hi, Daniel Walker wrote:
#include <boost/lambda/lambda.hpp> #include <boost/utility/result_of.hpp> using namespace boost;
template<class Functor, class Arg1, class Arg2> void f(Functor const&, Arg1 const&, Arg2 const&) { typedef typename result_of< Functor(Arg1, Arg2)
::type result_type; }
int main() { using namespace lambda; int x = 0, y = 0; f(ret<int>(_1 + _2), x, y); }
In fact, this code works without that patch using something like this: http://tinyurl.com/2xw4s2
2) Boost.Lambda instructs users to expose a template sig<tuple<ARG1, ..., ARGN>, and it also uses this convention internally.
How about introduce a converter function like this?: http://tinyurl.com/2f5hn6 Anyway I'm hoping your work will make lambda support result_of! Regards, -- Shunsuke Sogame

On 3/20/07, shunsuke <pstade.mb@gmail.com> wrote:
In fact, this code works without that patch using something like this: http://tinyurl.com/2xw4s2
This is a good way to work around the problem in boost user level code. I'm going to be using specialization of result_of for lambda_functor in my code for BOOST_VERSION < 103500, assuming this is fixed for 1.35.
2) Boost.Lambda instructs users to expose a template sig<tuple<ARG1, ..., ARGN>, and it also uses this convention internally.
How about introduce a converter function like this?: http://tinyurl.com/2f5hn6
That's another good idea.
Anyway I'm hoping your work will make lambda support result_of!
Me too. Thanks!
participants (6)
-
Arkadiy Vertleyb
-
Daniel Walker
-
Douglas Gregor
-
Eric Niebler
-
Giovanni Piero Deretta
-
shunsuke