
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