From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-03-22 09:53:26


Hello,

It was pointed out to me in another thread (http://tinyurl.com/2l22av)
that the following is an incorrect usage of result_of.

On 3/21/07, Daniel Walker <daniel.j.walker_at_[hidden]> wrote:
>
> struct result_functor {
> // Define a result trait such that result<F(F,A1)>::type is A1.
> BOOST_FIXED_ARITY_FUNCTOR_RESULT(2, A1)
>
> template<class Arg>
> typename result<result_functor(result_functor, Arg)>::type
> operator()(Arg const& a) const
> {
> return a;
> }
> };
>
[...]
>
> template<class F, class Arg>
> typename result_of<F(F, Arg)>::type
> f(F const& functor, Arg& a)
> {
> return functor(a);
> }
>
[...]
>
> result_of<
> sig_functor(sig_functor, value_type)
> >::type z = f(sig_f, x);

The result of documentation states:

"Given an lvalue f of type F and lvalues t1, t2, ..., tN of types T1,
T2, ..., TN, respectively, the type result_of<F(T1, T2, ...,
TN)>::type defines the result type of the expression f(t1, t2,
...,tN)."

So, obviously the usage above is wrong.

The reason it compiled (using gcc 4.1) was due to a misunderstanding I
had in converting result<> to sig<> and vice versa. I did ...

sig<tuple<F, T1, T2, ..., TN> > <--> result<F(F, T1, T2, ..., TN)>

It should have been.

sig<tuple<F, T1, T2, ..., TN> > <--> result<F(T1, T2, ..., TN)>

The attached patch is a revision of the first that corrects this
problem. Also, I added a check for the availability of result_of
through BOOST_NO_RESULT_OF and left the behavior unchanged for
platforms that result_of doesn't support.

With this revised patch you can do.

#include <boost/lambda/bind.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility/result_of.hpp>
using namespace boost;

struct result_functor {
    // Define a result trait such that result<F(A0)>::type is A0.
    BOOST_FIXED_ARITY_FUNCTOR_RESULT(1, A0)

    template<class Arg>
    typename result<result_functor(Arg)>::type
    operator()(Arg const& a) const
    {
        return a;
    }
};

struct sig_functor {
    template<class Args>
    struct sig {
        typedef typename tuples::element<1, Args>::type type;
    };

    template<class Arg>
    typename sig<tuple<sig_functor, Arg> >::type
    operator()(Arg const& a) const
    {
        return a;
    }
};

template<class F, class Arg>
typename result_of<F(Arg)>::type
f(F const& functor, Arg& a)
{
    return functor(a);
}

int main()
{
    using namespace boost::lambda;

    typedef char value_type;
    value_type x;
    result_functor result_f;
    value_type y = f(bind(result_f, _1), x);
    sig_functor sig_f;
    value_type z = f(bind(sig_f, _1), x);
}

And additionally with my previously submited result_of patch ...

    result_of<
        sig_functor(value_type)
>::type z = f(sig_f, x);

I ran the lambda regressions again and they passed. Let me know if you
see more problems.

Thanks!
Daniel