Passing capturing lambda as function pointer

前端 未结 9 2232
-上瘾入骨i
-上瘾入骨i 2020-11-21 06:58

Is it possible to pass a lambda function as a function pointer? If so, I must be doing something incorrectly because I am getting a compile error.

Consider the follo

9条回答
  •  野性不改
    2020-11-21 07:21

    Lambda expressions, even captured ones, can be handled as a function pointer (pointer to member function).

    It is tricky because an lambda expression is not a simple function. It is actually an object with an operator().

    When you are creative, you can use this! Think of an "function" class in style of std::function. If you save the object you also can use the function pointer.

    To use the function pointer, you can use the following:

    int first = 5;
    auto lambda = [=](int x, int z) {
        return x + z + first;
    };
    int(decltype(lambda)::*ptr)(int, int)const = &decltype(lambda)::operator();
    std::cout << "test = " << (lambda.*ptr)(2, 3) << std::endl;
    

    To build a class that can start working like a "std::function", first you need a class/struct than can store object and function pointer. Also you need an operator() to execute it:

    // OT => Object Type
    // RT => Return Type
    // A ... => Arguments
    template
    struct lambda_expression {
        OT _object;
        RT(OT::*_function)(A...)const;
    
        lambda_expression(const OT & object)
            : _object(object), _function(&decltype(_object)::operator()) {}
    
        RT operator() (A ... args) const {
            return (_object.*_function)(args...);
        }
    };
    

    With this you can now run captured, non-captured lambdas, just like you are using the original:

    auto capture_lambda() {
        int first = 5;
        auto lambda = [=](int x, int z) {
            return x + z + first;
        };
        return lambda_expression(lambda);
    }
    
    auto noncapture_lambda() {
        auto lambda = [](int x, int z) {
            return x + z;
        };
        return lambda_expression(lambda);
    }
    
    void refcapture_lambda() {
        int test;
        auto lambda = [&](int x, int z) {
            test = x + z;
        };
        lambda_expressionf(lambda);
        f(2, 3);
    
        std::cout << "test value = " << test << std::endl;
    }
    
    int main(int argc, char **argv) {
        auto f_capture = capture_lambda();
        auto f_noncapture = noncapture_lambda();
    
        std::cout << "main test = " << f_capture(2, 3) << std::endl;
        std::cout << "main test = " << f_noncapture(2, 3) << std::endl;
    
        refcapture_lambda();
    
        system("PAUSE");
        return 0;
    }
    

    This code works with VS2015

    Update 04.07.17:

    template  struct function
    : public function {};
    
    template  struct function {
    private:
        C mObject;
    
    public:
        function(const C & obj)
            : mObject(obj) {}
    
        template typename 
        std::result_of::type operator()(Args... a) {
            return this->mObject.operator()(a...);
        }
    
        template typename 
        std::result_of::type operator()(Args... a) const {
            return this->mObject.operator()(a...);
        }
    };
    
    namespace make {
        template auto function(const C & obj) {
            return ::function(obj);
        }
    }
    
    int main(int argc, char ** argv) {
       auto func = make::function([](int y, int x) { return x*y; });
       std::cout << func(2, 4) << std::endl;
       system("PAUSE");
       return 0;
    }
    

提交回复
热议问题