加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

将c lambda转换为c函数

发布时间:2020-12-16 07:01:28 所属栏目:百科 来源:网络整理
导读:我正在编写一些包装代码,其中外部库调用c函数(使用可变参数模板等).关键的一点是外部库需要一个c函数,通常没问题,因为这是合法的: LibraryFuncType fn = [](params) { ... } 虽然我可以轻松地手动执行此操作,但我希望使用以下内容自动执行包装: function_(
我正在编写一些包装代码,其中外部库调用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");
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读