Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2008-04-30 12:19:07


On Wed, Apr 30, 2008 at 12:04 AM, shunsuke <pstade.mb_at_[hidden]> wrote:
> David Abrahams wrote:
> > To deal with this I need something more like
> >
> >
> > template <class F>
> > typename result_of<
> > typename mpl::if_<
> > is_class<F>
> > , F
> > , typename add_pointer<F>::type
> > >::type()
> > >::type
> > call(F const& f)
> > {
> > return f();
> > }
> >
> > Is there an easier way?
>
> How about `boost::decay`?
> Or an "imaginary" function `apply` might be better.
>
> template<class F>
> typename result_of<typeof_apply(F const &)>::type
> call(F const &f)
> {
> return apply(f);
> }
>

Aha! That just made me realize that I didn't fully understand what
Dave was getting at yesterday. call() uses call-by-reference, and
since boost::result_of<> treats all references as function references,
you have to somehow decompose the reference before hand to determine
what to pass to result_of<> so that it will do the right thing. OK.
Then the snippet I sent yesterday will work for function references
but not references to function objects. Still, I think the best thing
to do in this case is to make call() accept only first-class function
objects by value... especially since all the tools needed to treat
built-in functions or references to function objects as values will be
available in C++0x as soon as you #include <functional>. For example:

template <class F>
typename std::result_of<const F()>::type
call(const F f)
{
    return f();
}

int f() { return 0; }

struct g {
    typedef int result_type;
    int operator()() const { return 0; };
};

// Promote built-in function to first-class
int x = call(std::function<int()>(f));

// Call-by-reference
int y = call(std::cref(g()));

// Call-by-value
int z = call(g());

Actually, you don't need to use function<> with the call() above since
the function reference will be deduced correctly, but if call() used a
concept to require AdaptableGenerator or the like, then you would have
wrap the built-in in an actual functor.

I believe that on modern optimizing compilers this would be as
efficient as implementing call() using call-by-reference, and it's
much simpler than using meta programming to analyze the reference
argument. Is there a reason not to use this idiom? ... other than
using references for some sort of sub-class polymorphic functors,
which isn't even remotely cool.

Daniel Walker


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk