Home > Blockchain >  wrapping templated function call in another function call
wrapping templated function call in another function call

Time:03-20

Anyone know if it is possible to do something similar to the following:

void my_inner_func(int i, double d, ...) { 
    // do stuff here
}

template <typename Func, typename... Args>
void my_outer_func(Func&& f,Args&&... args){
    // do other stuff here, put this inside loop, etc
    f(std::forward<Args>(args)...);
}

template <typename OuterFunc,typename InnerFunc,typename... Args>
void func(OuterFunc&& outer, InnerFunc&& inner, Args&&...args) {
    outer(std::forward<InnerFunc>(inner),std::forward<Args>(args)...);
}

Where the calling code might look something like this:

func(my_outer_func, my_inner_func, 1, 2.0, ...);

The issue that I am running into is that the type of the OuterFunction cannot be deduced. I've tried a bunch of different things including converting func to a functor and making OuterFunc a template template parameter.

CodePudding user response:

my_outer_func needs to be wrapped in a lambda when passing it to func:

func([](auto &&... params){my_outer_func(decltype(params)(params)...);}, my_inner_func, 1, 2.0);

Where decltype(params)(params) is equivalent to std::forward<decltype(params)>(params), but with less typing.

Or, my_outer_func can itself be a lambda:

auto my_outer_func = []<typename Func, typename... Args>(Func&& f,Args&&... args)
{
    f(std::forward<Args>(args)...);
};

Explicit template parameters in a lambda are a C 20 feature. Pre-C 20 you'd have to use auto, like in the first example.

CodePudding user response:

It works if you make my_outer_func a function object rather than a function:

struct my_outer_func {
    template <typename Func, typename... Args>
    void operator()(Func&& f,Args&&... args) const {
        // do other stuff here, put this inside loop, etc
        f(std::forward<Args>(args)...);
    }
};

Then:

func(my_outer_func(), my_inner_func, 1, 2.0);

If you don't like the parentheses at the call site, you can remove them if you create a global struct instance instead:

struct {
    template <typename Func, typename... Args>
    void operator()(Func&& f,Args&&... args) const {
        // do other stuff here, put this inside loop, etc
        f(std::forward<Args>(args)...);
    }
} my_outer_func;
  • Related