Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;以函数作为模板参数的函数调用包装器_C++_Templates_Variadic Templates_Variadic Functions - Fatal编程技术网

C++ C++;以函数作为模板参数的函数调用包装器

C++ C++;以函数作为模板参数的函数调用包装器,c++,templates,variadic-templates,variadic-functions,C++,Templates,Variadic Templates,Variadic Functions,我试图创建一个通用包装函数,它将函数作为模板参数,并将与该函数相同的参数作为其参数。例如: 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

我试图创建一个通用包装函数,它将函数作为模板参数,并将与该函数相同的参数作为其参数。例如:

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;
}
我找了相关的帖子,发现了这些,但没有一个是我想要做的。这些帖子大多涉及函数对象。我想做的事可能吗


作为对前两个回答的回应,我编辑了这个问题,以明确我需要能够在包装函数中工作(即,在调用包装函数之前和之后修改一些全局状态)

您可能需要

template <typename F>
class Wrapper {
public:
    Wrapper(F *func) : function(func) {}
    operator F* () { return function; }
    F *function;
};
模板
类包装器{
公众:
包装器(F*func):函数(func){}
运算符F*(){返回函数;}
F*函数;
};

可以像
void(*funcPtr)(int)=包装器(&someFunction)那样使用它

我认为这将是做你想做的事情的简洁方式:

template <typename F>
F* wrapper(F* pFunc)
{
    return pFunc;
}
模板结构包装器\u impl;
模板
结构包装器\u impl{
静态R换行(Args…Args){
//东西
返回f(args…);
}
};
模板
constexpr auto wrapper=wrapper\u impl::wrap;
用作
包装器

#包括
#包括
结构c_api_接口{int(*func_a)(int,int);int(*func_b)(char,char,char);};
intfoo(inta,intb){返回a+b;}
int-bar(字符a,字符b,字符c){返回a+b*c;}
模板
typename std::result\u of::type
包装器(Args…Args){

std::cout你可以尝试类似的东西(难看,但有效)

#包括
#包括
结构包装器
{
包装器(ctx)
{

std::我能感谢您的回复吗,但这并不是我在原始帖子中要求的。在您的解决方案中,如果我调用
funcPtr()
它调用
someFunction
。我希望它调用一个函数,在调用
someFunction
前后都做一些工作@Eric,现在我明白你想要什么,也不明白你为什么要找这么难的方法。没有捕获的Lambda函数可以转换为c函数指针:
void(*funcPtr)(int)=[](int a){/*smth*/}
-调用包装函数和lambdaI内部的前/后例程一开始就尝试了这一点。我相信lambdas只有在函数指针没有捕获时才可以转换为函数指针,为了实现这一通用性,我需要编写一个lambda来捕获它将要调用的函数,但也许有一种方法可以实现我所缺少的功能。谢谢响应,但这不符合我的要求。我需要能够在调用包装函数(在本例中为
foo
)之前和之后在包装函数中执行一些工作。因此包装函数需要与包装函数具有相同的函数签名。我不确定是否可以从模板参数中检索签名(即
Ts…Args
)但您可以将它们保存为延迟调用,如图所示,然后在
Wrapper::operator()
使用保存的参数在调用基础func之前和之后执行操作感谢您,这非常有效!)对于其他人:我认为变量模板是c++14的一个特性,因此可能无法在所有编译器上工作wrapper_impl::wrap
完成了大致相同的任务。这可以适应可选参数吗?这意味着包装函数中的可选参数在包装函数中也是可选的。在这个变量中,必须指定所有参数。您认为可以扩展包装成员函数吗?我尝试添加了模板中有一个typename T,模板参数也有一个T*T。然后通过T->f(args…)调用函数,但在C++17中没有解决这个错误:“错误:未定义模板的隐式实例化”谢谢!我将此更改为可接受的答案,因为它比@T.C更短,只使用函数而不是结构,使用
std::forward
,并且(根据意见)更容易理解,因为你没有使用模板参数专门化。虽然我不得不承认std::forward只是在那里,因为我尝试了一些可以在MSVC下编译的东西,然后想“啊,去他妈的,不会发生……但是,嘿,继续前进”-)为看起来像要调用的普通函数的包装器声明别名的正确方法是什么?类似于使用_wrapped=wrapper;
(但此方法不起作用)。如果函数重载,此方法将无法通过
WRAPIT
宏工作。
template <typename F>
F* wrapper(F* pFunc)
{
    return pFunc;
}
my_interface.func_a = wrapper(foo);
my_interface.func_a(1, 3);
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;
#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;
}
#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;
}