C++ lambda with captures as a function pointer

后端 未结 8 797
离开以前
离开以前 2020-11-22 15:35

I was playing with C++ lambdas and their implicit conversion to function pointers. My starting example was using them as callback for the ftw function. This works as expecte

8条回答
  •  太阳男子
    2020-11-22 15:45

    ORIGINAL

    Lambda functions are very convenient and reduce a code. In my case I needed lambdas for parallel programming. But it requires capturing and function pointers. My solution is here. But be careful with scope of variables which you captured.

    template
    Tret lambda_ptr_exec(T* v) {
        return (Tret) (*v)();
    }
    
    template
    Tfp lambda_ptr(T& v) {
        return (Tfp) lambda_ptr_exec;
    }
    

    Example

    int a = 100;
    auto b = [&]() { a += 1;};
    void (*fp)(void*) = lambda_ptr(b);
    fp(&b);
    

    Example with a return value

    int a = 100;
    auto b = [&]() {return a;};
    int (*fp)(void*) = lambda_ptr(b);
    fp(&b);
    

    UPDATE

    Improved version

    It was a while since first post about C++ lambda with captures as a function pointer was posted. As It was usable for me and other people I made some improvement.

    Standard function C pointer api uses void fn(void* data) convention. By default this convention is used and lambda should be declared with a void* argument.

    Improved implementation

    struct Lambda {
        template
        static Tret lambda_ptr_exec(void* data) {
            return (Tret) (*(T*)fn())(data);
        }
    
        template
        static Tfp ptr(T& t) {
            fn(&t);
            return (Tfp) lambda_ptr_exec;
        }
    
        template
        static void* fn(void* new_fn = nullptr) {
            static void* fn;
            if (new_fn != nullptr)
                fn = new_fn;
            return fn;
        }
    };
    

    Exapmle

    int a = 100;
    auto b = [&](void*) {return ++a;};
    

    Converting lambda with captures to a C pointer

    void (*f1)(void*) = Lambda::ptr(b);
    f1(nullptr);
    printf("%d\n", a);  // 101 
    

    Can be used this way as well

    auto f2 = Lambda::ptr(b);
    f2(nullptr);
    printf("%d\n", a); // 102
    

    In case return value should be used

    int (*f3)(void*) = Lambda::ptr(b);
    printf("%d\n", f3(nullptr)); // 103
    

    And in case data is used

    auto b2 = [&](void* data) {return *(int*)(data) + a;};
    int (*f4)(void*) = Lambda::ptr(b2);
    int data = 5;
    printf("%d\n", f4(&data)); // 108
    

自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题