调用无实例的无状态Lambda(仅类型) [英] Calling a stateless lambda without an instance (only type)

查看:74
本文介绍了调用无实例的无状态Lambda(仅类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为注册回调" C库中的接口类型.该库使您可以通过接受参数定义列表来注册可变"函数,这一事实使问题变得非常复杂.然后在回调时,该函数应从类型擦除的参数列表中提取其参数.好老的C ...

I'm trying to write a wrapper for a "register callback" type of interface from a C library. The issue is quite complicated by the fact that, the library lets you register "variadic" functions by accepting a list of parameter definitions. Then at callback time, the function is expected to extract its arguments from a type-erased list of arguments. Good old C...

我要创建的接口是接受任何函数,甚至是lambda,并自动生成所有机器以正确注册此函数,以及注册参数并在回调期间提取它们.因此,用户只需要键入:

The interface I'm trying to create is to accept any function, even a lambda, and automatically generate all the machinery to correctly register this function, along with registering the arguments and extracting them during callback time. So the user should only have to type:

register_callback("Callback Name", [](int i){return i+0.5;});

现在从理论上讲这是可行的,但是在某一点上,我需要能够不带任何实例但只能访问其类型的情况下调用lambda.我不明白为什么,但是删除了无状态(非捕获)lambda的默认构造函数,因此我不能简单地根据其类型进行默认构造.我打算做的是看起来很脏,但是应该可以解决此问题:

Now this is theoretically possible, but at one point, I need to be able to call the lambda without any instance, but with access to only its type. I don't understand why, but the default constructor of a stateless (non-capturing) lambda is deleted, so I can't simply default-construct from its type. What I'm planning to do instead is a very dirty-looking, but should probably be OK way to work around this:

template <class Func, class RET, class ...ARGS>
struct from_stateless {
    static RET to_function(ARGS...args) {
        RET (*f)(ARGS...) = *(Func *)(0);
        return f(args...);
    }
};

所以from_stateless<LAMBDA_TYPE, RET, ARGS...>::to_function实际上是我可以不带参数调用的函数指针,更重要的是我可以作为TEMPLATE ARGUMENT传递的函数指针.

so that from_stateless<LAMBDA_TYPE, RET, ARGS...>::to_function is actually a function pointer that I can call without an argument and more importantly one that I can pass as a TEMPLATE ARGUMENT.

在通常情况下,RET (*f)(ARGS...) = *(Func *)(0);行会自杀,但是在此用例中确实应该是安全的,不是吗?毕竟,转换后获得的函数指针不可能在任何Universe中都取决于lambda实例.

Under normal circumstances, the line RET (*f)(ARGS...) = *(Func *)(0); would be suicide, but it really should be safe with this use case, isn't it? After all, the function pointer obtained after conversion couldn't in any universe possibly depend on the lambda instance.

所以,问题是,只要确保类型确实是无状态的lambda,这样做是否安全?还是我错过了什么?请注意,如果RET (*f)(ARGS...) = *(Func *)(0);会意外关闭,则会触发编译器错误.

So, the question is, is it safe to do this as long as I make sure that the type is indeed a stateless lambda? Or am I missing something? Note that the RET (*f)(ARGS...) = *(Func *)(0); would trigger a compiler error if a closure accidentally slips through.

澄清:我不能仅仅将lambda衰减到函数指针并进行注册,因为lambda的签名与"Register"方法不兼容. register方法期望具有签名的函数:void (*)(int number_of_args, TypeErasedValue * arguments, TypeErasedValue * result)因此,您知道,我需要(并且已经这样做),通过模板元编程,生成一个以lambda类型为模板的自由函数,以充当预期和预期之间的适配器.实际签名.

CLARIFICATION: I can't just decay the lambda to a function pointer and register it, since the signature of the lambda is not compatible with the "Register" method. The register method expects a function with signature: void (*)(int number_of_args, TypeErasedValue * arguments, TypeErasedValue * result) So you see, I need to (and already do), through template metaprograming, generate a free function templated on the type of the lambda to act as an adaptor between the expected and the actual signatures.

推荐答案

如果您利用lambda无需捕获即可看到其包围范围的static当地人的事实,它甚至比@Yakk的答案还要容易.他们.利用这一事实,您可以将用户提供的无状态lambda包装在具有所需签名的自己的无状态lambda中,然后将后者转换为函数指针.

It gets even easier than @Yakk's answer if you take advantage of the fact that a lambda can see the static locals of its enclosing scope without needing to capture them. Using this fact you can wrap the user-provided stateless lambda in your own stateless lambda with the required signature, and convert the latter into a function pointer.

using callback = void (*)(int, TypeErasedValue*, TypeErasedValue*);

template <typename F>
callback stateless_to_callback(F f) {
    static F static_f = f;
    return [](int argc, TypeErasedValue* argv, TypeErasedValue* result) {
        // extract arguments from argv
        auto r = static_f( /* arguments... */ );
        // store r in result
    };
}

这篇关于调用无实例的无状态Lambda(仅类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆