|
Boost : |
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-03-21 13:47:06
On 3/20/07, shunsuke <pstade.mb_at_[hidden]> 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk