0

I'm trying to create a delayable call object. Something along the lines of (pseudo-code):

template <class FN>
struct delayable_call
{
    return-type-of-FN call(); // <-- I'd like to use result_of here.

    template<class ArgTypes...>
    delayable_call(FN* pFn, ArgTypes... args);

    FN* fn;
    args-saving-struct;
};

I tried using result_of::type for the return type of call, but get errors during instantiation of the template because apparently the argument types need to be specified separately.

Instantiation:

int foo(bool, double); // function prototype.

delayable_call<int(bool, double)> delayable_foo(foo, false, 3.14); // instantiation

The error messages and documentation I've read about result_of seem to indicate that the argument types must also be specified. So instead of result_of<FN>::type, I'd need to specify result_of<FN(bool, double)>::type. This does actually fix the compilation problem I'm having, but breaks the generality of the template.

So, how can I use result_of with a template parameter when the template parameter represents the function signature?

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
CppWoman
  • 137
  • 1
  • 2
  • 7

1 Answers1

1
template <class FN> struct delayable_call;
template<class R, class...Args> delayable_call<R(Args...)>{
  typedef R(*)(Args...) pFN;

replace your delayable_call with a specialization, and you will extrace both R and Args.... You need Args... anyhow to store the parameters.

However, a library-strength delayable call will end up using type erasure. The easiest way is a simple std::function<R()> where you shove a lambda into it:

int foo(double);
double x = 7;
std::function<int()> delayed_foo = [x]{ return foo(x); }

and capture by value unless you really, really mean it to capture by reference.

You could deduce R via:

template<typename Fn, typename... Args>
std::function< typename std::result_of<Fn(Args...)>::type()>
make_delayed_call( Fn&& fn, Args&&... args ) {
  return [=]{ return fn(std::move(args)...); }
}

which should deduce your R from the callable object and the arguments. This captures everything by copy -- capture by move requires either more boilerplate, or C++14.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • That's mean, though: What if you want to delay calling a lambda or a `std::function`? – Kerrek SB Jan 02 '14 at 19:31
  • Does this help? http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda –  Jan 02 '14 at 19:32
  • @KerrekSB that is a different problem -- the OP asked for `delayable_call` to correspond to a delayable call on a function pointer. The general version ends up using type erasure on an object that wraps both the args and the callable, and `delayable_call` is templated *only* on the `R` value. The `R` value can be deduced by a `make_delayable_call` function. If the OP wants that more complex one, I can write it. – Yakk - Adam Nevraumont Jan 02 '14 at 19:37