将c lambda转换为c函数
我正在编写一些包装代码,其中外部库调用c函数(使用可变参数模板等).关键的一点是外部库需要一个c函数,通常没问题,因为这是合法的:
LibraryFuncType fn = [](params) { ... } 虽然我可以轻松地手动执行此操作,但我希望使用以下内容自动执行包装: function_(context,"name",myfunc); 要做到这一点,我需要一个类似于以下的函数: template <ReturnType,ParamTypes...> static void function_(Context &ctx,const std::string &name,std::function<ReturnType(ParamTypes...)> fn) { ctx.registerFunction(name,[fn](State *state) -> int { Context ctx(state); return apply_helper<sizeof..(ParamTypes)>::apply(ctx,fn); }); } 其中第二个参数“ctx.registerFunction”的类型为LibraryFuncType. 但这当然是有问题的,因为由于捕获’fn’,lambda转换不再合法.但是,如果我没有捕获’fn’,那么我将无法在lambda中访问它. 我认为解决这个问题的唯一方法是使用静态变量,但我不清楚引入静态变量的最佳方法.我目前的解决方案是: template <typename ReturnType,typename... ParamTypes> struct function_helper { static std::function<ReturnType(ParamTypes...)> fn; function_helper(std::function<ReturnType(ParamTypes...)> _fn) { fn = _fn; } static void registerFn(Context &ctx,const std::string &name) { ctx.registerFn(name,[](state *state) -> int { Context ctx(state); return apply_helper<sizeof...<ParamTypes>>::apply(ctx,fn); }); } }; template <typename ReturnType,typename... ParamTypes> std::function<ReturnType(ParamTypes...)> function_helper<ReturnType,ParamTypes...>::fn; template <typename ReturnType,typename... ParamTypes> void function_(Context &ctx,std::function<ReturnType(ParamTypes...)> fn) { function_helper<ReturnType,ParamTypes...> reg(fn); reg.registerFn(ctx,name); } 虽然从技术上来说这很有效,但它显然很危险(而且很容易),因为如果我在具有相同签名的两个函数上使用’function_helper’,它将为其中一个设置’fn’. 另外,我可以通过在’function_’中声明一个静态变量来做同样的危险静态变量.我上课时希望能够深入了解解决问题的正确方法. 有没有人知道使用不需要捕获的lambda的更好方法(或者,一种将捕获的lambda转换为c函数的方法)? 解决方法
避免在注册代码中使用函数指针值的一种方法是使其成为模板参数.不幸的是,我无法想出一个非常好的符号.但是,如果使用下面的内容注册函数是可以接受的,那么这样做是非常简单的:
RegisterHelper<decltype(foo)>::doRegister<&foo>("foo"); 有了这个,RegisterHelper是一个带有静态函数doRegister()的类模板,它将函数指针作为模板参数.找到一种直接调用函数模板并让它找出类型的方法会很好: doRegister<&foo>("foo"); 但是,我还没有找到办法做到这一点,因为函数模板不能部分专门化(否则我认为这是可能的).下面粗略概述了代码的外观.代码不会尝试执行任何实际调用该函数所需的委托.它仅用于显示如何传入函数指针.演示硬编码某些类型,但仅仅因为添加任何编组代码会隐藏正在发生的事情. #include <string> #include <iostream> struct State; typedef std::string (*function_type)(State*); void registerFunction(std::string const& name,function_type function) { std::cout << "calling '" << name << "': " << function(0) << "n"; } template <typename T> class RegisterHelper; template <typename RC,typename... Args> class RegisterHelper<RC(Args...)> { public: template <RC (*function)(Args...)> static void doRegister(std::string const& name) { registerFunction(name,[](State*) -> std::string { return function(17,4.0); }); } }; std::string foo(int,double) { return "foo"; } std::string bar(int,double) { return "bar"; } int main() { RegisterHelper<decltype(foo)>::doRegister<&foo>("foo"); RegisterHelper<decltype(bar)>::doRegister<&bar>("bar"); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |