C++ function call wrapper with function as template argument

天大地大妈咪最大 提交于 2019-11-27 01:29:27

问题


I'm trying to create a generic wrapper function that takes a function as a template argument and takes the same arguments as that function as its arguments. For example:

template <typename F, F func>
/* return type of F */ wrapper(Ts... Args /* not sure how to get Ts*/)
{
    // do stuff
    auto ret = F(std::forward<Ts>(args)...);
    // do some other stuff
    return ret;
}

The solution needs to be castable to a function pointer with the same type as func so that I can pass it to a C api. In other words, the solution needs to be a function and not a function object. Most importantly, I need to be able to do work in the wrapper function.

If the inline comments aren't clear, I'd like to be able to do something like the following:

struct c_api_interface {
    int (*func_a)(int, int);
    int (*func_b)(char, char, char);
};

int foo(int a, int b)
{
    return a + b;
}

int bar(char a, char b, char c)
{
    return a + b * c;
}

c_api_interface my_interface;
my_interface.func_a = wrapper<foo>;
my_interface.func_b = wrapper<bar>;

I looked for related posts and found these, but none of them are quite what I'm trying to do. Most of these posts concern function objects. Is what I'm trying to do even possible?

Function passed as template argument

Function wrapper via (function object) class (variadic) template

How does wrapping a function pointer and function object work in generic code?

How do I get the argument types of a function pointer in a variadic template class?

Generic functor for functions with any argument list

C++ Functors - and their uses

In response to the first 2 responses, I edited the question to make it clear that I need to be able to do work in the wrapper function (i.e. modify some global state before and after the call to the wrapped function)


回答1:


#include <utility>
#include <iostream>

struct c_api_interface { int (*func_a)(int, int); int (*func_b)(char, char, char); };
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }


template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args... args) {
   std::cout << "and ....it's a wrap ";
   return fn(std::forward<Args>(args)...);
}
#define WRAPIT(FUNC) wrapper<decltype(&FUNC), &FUNC>

int main() {
  c_api_interface my_interface;
  my_interface.func_a = WRAPIT(foo);
  my_interface.func_b = WRAPIT(bar);

  std:: cout << my_interface.func_a(1,1) << std::endl;
  std:: cout << my_interface.func_b('a','b', 1) << std::endl;

  return 0;
}

see http://rextester.com/ZZD18334




回答2:


template<class F, F f> struct wrapper_impl;
template<class R, class... Args, R(*f)(Args...)>
struct wrapper_impl<R(*)(Args...), f> {
    static R wrap(Args... args) {
        // stuff
        return f(args...);
    }
};

template<class F, F f>
constexpr auto wrapper = wrapper_impl<F, f>::wrap;

Use as wrapper<decltype(&foo), foo>.




回答3:


I think that will be the concise way to do what you want:

template <typename F>
F* wrapper(F* pFunc)
{
    return pFunc;
}

and use it like this:

my_interface.func_a = wrapper(foo);
my_interface.func_a(1, 3);



回答4:


you may try something like that (Ugly, but works)

#include <iostream>
#include <functional>

struct wrapper_ctx
{
  wrapper_ctx ()
  {
    std::cout << "Before" << std::endl;
  }
  ~wrapper_ctx ()
  {
    std::cout << "after" << std::endl;
  }
};

template <typename F, typename... Args>
auto executor (F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type
{
  wrapper_ctx ctx;
  return std::forward<F>(f)( std::forward<Args>(args)...);

}

template <typename F>
class wrapper_helper;


template<typename Ret, typename... Args>
class wrapper_helper <std::function<Ret(Args...)>>
{
  std::function<Ret(Args...)> m_f;
public:
  wrapper_helper( std::function<Ret(Args...)> f ) 
      : m_f(f) {}
  Ret operator()(Args... args) const 
  { 
    return executor (m_f, args...); 
  }
};

template <typename T>
wrapper_helper<T> wrapper (T f)
{
  return wrapper_helper <T>(f);
}


int sum(int x, int y)
{
  return x + y;
}


int main (int argc, char* argv [])
{

  std::function<int(int, int)> f = sum;
  auto w = wrapper (f);

  std::cout << "Executing the wrapper" << std::endl;
  int z = w(3, 4);

  std::cout << "z = " << z << std::endl;
}



回答5:


you probably need something like

template <typename F>
class Wrapper {
public:
    Wrapper(F *func) : function(func) {}
    operator F* () { return function; }
    F *function;
};

Which you can use like void (*funcPtr)(int) = Wrapper<void(int)>(&someFunction);



来源:https://stackoverflow.com/questions/36492029/c-function-call-wrapper-with-function-as-template-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!