简体   繁体   中英

C++ pass "this" to an imported lambda function from another file (in order to access member variables)

I need to pass a lambda function to a library (which then gets executed in certain conditions) , therefore I cannot modify the type signature.

But the "passing" of the lambda function happens inside a class / struct and the function needs to access other member variables . This can normally be achieved by capturing "this" in the lambda function declaration ( [this](...){} ).

But the problem is, I would like to declare the lambda function in a separate file than the struct is (due to code clarity and better project structure) .

So how do I pass the "this" to the imported lambda function?

This is basically what I would like to achieve:

/* -- handlers.h -- */
auto message = [/* how to capture "this" (worker_t) here? */](WSConnection *ws, std::string_view message)
{
    if (message == "closedown")
    {
        // this "listen_socket_" is a member of the worker_t that this function needs to access
        us_listen_socket_close(0, listen_socket_);
        ws->close();
    }
}

/* -- main.cpp -- */
#include "handlers.h"

struct worker_t
{
    // the lambda function needs to access these members
    struct us_listen_socket_t *listen_socket_;
    std::shared_ptr<uWS::App> app_;

    void work()
    {
        app_ = std::make_shared<uWS::App>();

        app_->ws<PerSocketData>("/*", {
           .message = message, // I would like to just PASS the function here, not declare it
           // ...
        });

        // ...
    }
};

Is there a better solution than declaring a "wrapper" lambda function in-place and then calling the imported message function inside it like this?

/* -- handlers.h -- */
auto message = [](worker_t* self, WSConnection *ws, std::string_view message)
{
    if (message == "closedown")
    {
        /* Bye bye */
        us_listen_socket_close(0, self->listen_socket_);
        ws->close();
    }
}

/* -- main.cpp -- */
#include "handlers.h"

struct worker_t
{
    // the lambda function needs to access these members
    struct us_listen_socket_t *listen_socket_;
    std::shared_ptr<uWS::App> app_;

    void work()
    {
        app_ = std::make_shared<uWS::App>();

        app_->ws<PerSocketData>("/*", {
           .message = [this](WSConnection *ws, std::string_view message)
           {
               message(this, ws, message);
           }
           // ...
        });

        // ...
    }
};

You could make the lambda declared in "handlers.h" a higher-order function that returns a lambda.

auto make_message = [](worker_t* self)
{
    return [self](WSConnection *ws, std::string_view message)
    {
        if (message == "closedown")
        {
            /* Bye bye */
            us_listen_socket_close(0, self->listen_socket_);
            ws->close();
        }
    };
};

void worker_t::work()
{
    app_ = std::make_shared<uWS::App>();

    app_->ws<PerSocketData>("/*", {
       .message = make_message(this),
       // ...
    });

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM