dgrat
dgrat

Reputation: 2244

Variadic function wrapper considering references and const

I created a small function wrapper example. I want to make the wrapper consider whether or not the function called is using (const) references, meaning the output will be 4/5 and not 4/4, but I don't want to enforce reference usage if the wrapped function does not use them.

#include <iostream>
#include <string>

struct a {
  static void run(int cref) {
    cref = 5;
  };
};

struct b {
  static void run(int &cref) {
    cref = 5;
  };
};

template <class FTor>
struct foo {
    template <class ... Args>
    static void wrapper(Args ... args) {
      FTor::run(args ...);
    }
};


int main()
{
    int bar = 4;
    foo<a>::wrapper(bar);
    std::cout << bar;

    foo<b>::wrapper(bar);
    std::cout << bar;
}

Upvotes: 2

Views: 141

Answers (2)

Geezer
Geezer

Reputation: 5710

This is an attempt to answer what is possibly a misinterpretation of mine regarding the OP's request, as simple perfect forwarding solves the scenario described without resorting to the wrapped function arguments' types deduction.

Original answer: At least for the restricted use case such as you're presenting, you can use a small type trait struct to infer the type of single argument being passed to wrapper() from the type of argument of the functor:

#include <iostream>
#include <string>

struct a {
  static void run(int cref) {
    cref = 5;
  };
};

struct b {
  static void run(int &cref) {
    cref = 5;
  };
};

template <typename>
struct ArgType;

template <typename R, typename A>
struct ArgType<R(A)>
{ using type = A; };

template <class FTor>
struct foo {
    static void wrapper(typename ArgType<decltype(FTor::run)>::type args) {
      FTor::run(args);
    }
};

int main()
{
    int bar = 4;
    foo<a>::wrapper(bar);
    std::cout << bar;

    foo<b>::wrapper(bar);
    std::cout << bar;
}

Output:

45

Note this won't support perfect forwarding from within the wrapper, as wrapper() here is not itself part of a *type deducing context` -- as opposed to your snippet, that deduces but not based on what you want it to deduce. I'll hopefully find the time to add a generalized solution for variadic function template such as in your snippet, perfect forwarding included.

Upvotes: 1

SirGuy
SirGuy

Reputation: 10760

What about just using perfect forwarding?

template <class FTor>
struct foo {
    template <class ... Args>
    static void wrapper(Args && ... args) {
      FTor::run(std::forward<Args>(args) ...);
    }
};

That way, whatever ref-qualification the parameter has on input gets passed along to the inner function.

Upvotes: 3

Related Questions