c++ - 使用带有 lambdas/bind 的成员函数实现中间件函数

标签 c++ lambda c++17 generic-lambda

我有一个功能,Post() ,它有两个参数 - a std::string监听请求的路径,以及 std::function<void(Request &, Response &)>处理传入的请求。请注意,我无法修改 Post() .

例如:

m_server.Post("/wallet/open", [this](auto req, auto res)
{
    std::cout << req.body << std::endl;
}

我正在尝试通过中间件函数传递请求,然后转发到处理函数。

处理函数和中间件函数是成员函数。 Post() 绑定(bind)的设置发生在同一类的成员函数中。

这个有效:

m_server.Post("/wallet/open", [this](auto req, auto res){
    auto f = std::bind(&ApiDispatcher::openWallet, this, _1, _2);
    middleware(req, res, f);
});

但是,我连接了合理数量的请求,最好将其抽象为一个函数,这样我们就可以调用,例如

m_server.Post("/wallet/open", router(openWallet));

我设法让类似的东西工作,但我不知道如何在使用成员函数时让它工作。如果一切都是免费功能,这会很好用:

const auto router = [](auto function)
{
    return std::bind(middleware, _1, _2, function);
};

m_server.Post("/wallet/open", router(openWallet))
        .Post("/wallet/keyimport", router(keyImportWallet))
        .Post("/wallet/seedimport", router(seedImportWallet))
        .Post("/wallet/viewkeyimport", router(importViewWallet))
        .Post("/wallet/create", router(createWallet))

但是,我试图让它为成员函数工作的尝试不起作用,而且我无法真正弄清楚错误消息告诉我的是什么:

const auto router = [](auto function)
{
    return std::bind(&ApiDispatcher::middleware, _1, _2, function);
};

m_server.Post("/wallet/open", router(&ApiDispatcher::openWallet))
        .Post("/wallet/keyimport", router(&ApiDispatcher::keyImportWallet))
        .Post("/wallet/seedimport", router(&ApiDispatcher::seedImportWallet))
        .Post("/wallet/viewkeyimport", router(&ApiDispatcher::importViewWallet))
        .Post("/wallet/create", router(&ApiDispatcher::createWallet))

路由器功能本身就可以工作。我认为问题是我没有在 this 上调用处理函数.我试着这样做:

m_server.Post("/wallet/open", router(std::bind(&ApiDispatcher::openWallet, this, _1, _2)));

但随后我收到关于“指向成员的指针的参数数量错误”的错误。

这是一个重现问题的最小示例:

#include <iostream>
#include <string>
#include <functional>

using namespace std::placeholders;

class ApiDispatcher
{
    public:
        void middleware(std::string req, std::string res, std::function<void(std::string req, std::string res)> handler)
        {
            // do some processing
            handler(req + " - from the middleware", res);
        }

        void dispatch()
        {
            const auto router = [](auto function)
            {
                return std::bind(&ApiDispatcher::middleware, _1, _2, function);
            };

            /* Uncommenting this line breaks compilation */
            // Post("/wallet/open", router(&ApiDispatcher::openWallet));
        }

        void openWallet(std::string req, std::string res)
        {
            std::cout << req << std::endl;
        }

        void Post(std::string method, std::function<void(std::string req, std::string res)> f)
        {
            // wait for a http request
            f("request", "response");
        }    
};

int main()
{
    ApiDispatcher server;
    server.dispatch();
}

谢谢。抱歉帖子太长了。

最佳答案

您的路由器函数需要返回一个函数,该函数将使用该类的特定实例调用指定的成员函数。

void dispatch()
{
    const auto router = [this](auto function) {
        return std::bind(function, this, _1, _2);
    };

    Post("/wallet/open", router(&ApiDispatcher::openWallet));
}

或者,我最初错过了这个,通过中间件函数路由所有内容,这是我能找到的最简单的方法。

void dispatch()
{
    const auto router = [this](auto function) {
        return [this, function](auto a, auto b) {
            middleware(a, b, std::bind(function, this, _1, _2));
        };
    };

    Post("/wallet/open", router(&ApiDispatcher::openWallet));
}

或者,如果您更愿意使用绑定(bind),那么您必须首先强制将内部绑定(bind)作为一个函数,然后再执行。

void dispatch()
{
    const auto router = [this](auto function) {
        std::function<void(std::string, std::string)> func = std::bind(function, this, _1, _2);
        return std::bind(&ApiDispatcher::middleware, this, _1, _2, func);
    };

    Post("/wallet/open", router(&ApiDispatcher::openWallet));
}

关于c++ - 使用带有 lambdas/bind 的成员函数实现中间件函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53421055/

相关文章:

c++ - 如何在 C++ 中使用 TWAIN 设置扫描的 DPI

memory-leaks - 使用 lambdas 作为事件处理程序会导致内存泄漏吗?

java - Lambda 内部或Else获取有界通配符泛型

c++ - 如果 control-reaches-end-of-body 返回 nullopt,什么会中断?

c++ - '<一些系统头> : error: ‘<insert function here>’ is not a member of ‘std’ ' after moving source file

c++ - 解释这个 C++ 模板是如何工作的?

c++ - 使用 unique_ptr 进行转换的正确方法

c++ - CMake - 在顶级 CMakeLists.txt 中定义包含路径和库

c++ - Lambda 成员函数

c++ - 如何将 std::getline 转换为模板类型?