Home > database >  Making a template function mirror its template argument's signature
Making a template function mirror its template argument's signature

Time:02-11

I have a template function:

template <??? func>
??? wrapper(??? args) {
    // ... Stuff
    return func(args);
}

It should have the same signature as the func non-type template parameter.

The closest I've gotten is using auto in the template declaration and then using some form of function traits to deduce the return type, however, this method does not allow for deducing the parameters as a whole.

Ideally,

template <typename R, typename... Args, R(*func)(Args...)>
R wrapper(Args&&... args); // ...

or some other imaginary syntax would A. be allowed and B. deduce R and Args from func.

func must be specified at compile time and the function may not have any additional parameters (I need to take the address of the wrapper).

At this point I feel like my current solution,

template <auto func, typename... Args>
auto wrapper(Args&&... args) {
    return func(std::forward<Args>(args)...);
}

cannot be improved, since it appears impossible to generate "pure" variadic template arguments (getting them back after "storing" them anywhere (e.g. a tuple)). Which is sad, because it forces the Args to be provided manually. But of course I'd love to see someone prove me wrong on this!

CodePudding user response:

You can create traits to extract returs type and parameters. issue would be to handle arity only from function declaration.

If you can wrap in a class/functor, it would be possible:

template <auto func> struct wrapper_t;

template <typename Ret, typename ... Ts, Ret (*func)(Ts...)>
struct wrapper_t<func>
{
    Ret operator() (Ts... args) const { return func(std::forward<Ts>(args)...); }
};

// handle ellipsis functions ala printf
template <typename Ret, typename ... Ts, Ret (*func)(Ts..., ...)>
struct wrapper_t<func>
{
    template <typename ...EllipsisArgs>
    Ret operator() (Ts... args, EllipsisArgs&&... ellipisisArgs) const {
        return func(std::forward<Ts>(args)...,
                    std::forward<EllipsisArgs>(ellipisisArgs)...);
    }
};

template <auto func>
constexpr wrapper_t<func> wrapper{};

Demo

  • Related