Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapper for templated functions

What I am trying to accomplish is the following:

// or any templated function
template <typename... Args>
void function(Args... args) {}

// wrapper
void launch(???) { ??? }

int main()
{
    // first option
    launch(function, 1, 2, 3, 4);
    // second option
    launch<function>(1, 2, 3, 4);
}

As far as I can tell, the first option is impossibile since I would have to pass the specialized template function (which I'm trying to avoid).

For the second option I don't know if it's possible, I came up with the following not working implementation:

template <template <typename...> class Function, typename... Args>
void launch(Args... args)
{
    Function<Args...>(args...);
}

which ends up giving me:

main.cpp:18:5: error: no matching function for call to 'launch'
    launch<function>(1, 2, 3, 4);
    ^~~~~~~~~~~~~~~~
main.cpp:9:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Function'
void launch(Args... args)
     ^
1 error generated.

So, is something like this even possible?

like image 924
Manuel Avatar asked Apr 14 '26 04:04

Manuel


2 Answers

You basically cannot do anything with function templates except call them (and let arguments get deduced) or instantiate them (by manually specifying template arguments).

I believe there are also niche situations where template arguments may be deduced and a specific instantiation chosen without an actual call, but they don't help here AMA's answer shows how to do that!

Generic lambdas may or may not help you solve your problem, but you need one such forwarding lambda per function template you want to make "passable":

#include <functional>

// or any templated function
template <typename Arg1, typename Arg2>
void function(Arg1 arg1, Arg2 arg2) {}

int main()
{
    auto wrapper = [](auto arg1, auto arg2) {
        return function(arg1, arg2);
    };

    std::invoke(wrapper, 1, 2);
}

Demo

(Perfect-forwarding to a variadic function with a variadic lambda would be more complicated.)

So you might as well write function templates in the form of functor structs in the first place, or in the form of lambdas returned from non-template functions.

like image 200
Max Langhof Avatar answered Apr 15 '26 18:04

Max Langhof


How about:

template <typename ... Args>
void launch(void(*func)(Args...), Args&&... args) {
    func(std::forward<Args>(args)...);
}

calling launch:

launch(function, 1, 2, 3, 4);

Live example

like image 32
AMA Avatar answered Apr 15 '26 19:04

AMA



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!