1
votes

I want to build a functon template that takes any function pointer & its arguments list - and returns a (stateful) lambda that binds those arguments values inside (think std::bind but lambda-based)

#include <iostream>
#include <vector>

template <class ...D>
class DEB;

template <class Ret, class ... Args>
auto getLambdaFromFunction(Ret(*func)(Args...)) {
    return [func](Args ... ar){ // auto could work here but lambda is anyway templated by external template's Args
        func(ar...);
    };
}

template <class Ret, class ... Args>
auto wrapFunction(Ret(*func)(Args...),Args... args) {
    return [=](){
        func(args...);
    };
}

int doone(int a, float b) {
    std::cout << "do one";
    return a;
}

int main() {
    auto lw = getLambdaFromFunction(doone); // compiles
    lw(1,2.); // invokation works

    auto lambda_parameters_binded = wrapFunction(doone, 1,2.); // **ERROR**: no matching function for call
lambda_parameters_binded(); // see mom, no hands ie no arguments!
}

I believe I need to make somehow the variadic arguments to be captured inside the lambda in wrapFunction the default [=] capture seems not to understand variadic argument list

2
You should be able to expand the parameter pack in the lambda's capture - see Lambda Captures here - mattnewport
@mattnewport so when I refer to the parameter pack inside the lambda's body when calling func(args...) - it should automatically expand all of its elements to the lambda's [=] capture , right? everything should work out of the box? - barney
@mattnewport I just tried to write return [func,args...](){ func(args...); }; -- but still its not binding to the wrapFunction template - barney

2 Answers

5
votes

You should read the error description carefully, right now function accepts float, but you are passing double as a third parameter. Passing float will make it work:

auto lambda_parameters_binded = wrapFunction(doone, 1, 2.0f);

Run in online compiler

Also note that generated lambda does not return anything, you should add another return statement inside of lambda body:

return
(
    [=](void)
    {
        return(func(args...));
    }
);
1
votes

Another solution could be to have the function parameters, and the passed in parameter in different variadic template packs. That way there will be no ambiguity to generate the template function.

template <class Ret, class ... Args, class ... Params>
auto wrapFunction(Ret(*func)(Args...),Params... params) {
    return [=](){
        func(params...);
    };
}