C++11 C++;lambda回调

C++11 C++;lambda回调,c++11,lambda,callback,gcc5.2,C++11,Lambda,Callback,Gcc5.2,我正在尝试创建一个HTTP类,我想通过lambdas使用C++11(还不是C++14)回调。我有两个模型可用,第一个工作。。。但是看起来很丑。我的第二个目标不是编译(最后出错) 我不能使用std::function,因为这是一个嵌入式项目,该模板会生成大量代码 #include <cstring> class HTTP { public: void get1(const char* url, void* context, void (*callback)(void*, co

我正在尝试创建一个HTTP类,我想通过lambdas使用C++11(还不是C++14)回调。我有两个模型可用,第一个工作。。。但是看起来很丑。我的第二个目标不是编译(最后出错)

我不能使用
std::function
,因为这是一个嵌入式项目,该模板会生成大量代码

#include <cstring>

class HTTP
{
public:
    void get1(const char* url, void* context, void (*callback)(void*, const char*) )
    {
        callback(context, "");
    }

    void get2(const char* url, void (*callback)(const char*) )
    {
        callback("");
    }
};

void test()
{
    int k;
    HTTP http;
    http.get1( "http://google.com", &k, [](void* context, const char* s){
        int *k = (int*) context;
        *k = strlen(s);
    });

    // this does not compile, looking for other alternatives
    http.get2( "http://google.com", [&k](const char* s){
        k = strlen(s);
    });
}
#包括
类HTTP
{
公众:
void get1(常量字符*url,void*上下文,void(*回调)(void*,常量字符*)
{
回调(上下文“”);
}
void get2(常量字符*url,void(*回调)(常量字符*)
{
回拨(“”);
}
};
无效测试()
{
int k;
HTTP;
http.get1(“http://google.com“,&k,[](void*context,const char*s){
int*k=(int*)上下文;
*k=斯特伦(s);
});
//这不会编译,而是寻找其他替代方案
http.get2(“http://google.com“,[&k](常量字符*s){
k=斯特伦(s);
});
}
gcc错误(xtensa-esp32-elf-g++(crosstool NG crosstool-NG-1.22.0-80-g6c4433a)5.2.0)

HttpRequests.cpp:在函数“void test()”中:
HttpRequests.cpp:29:6:错误:调用“HTTP::get2(const char[18],test():)”时没有匹配的函数
});
^
HttpRequests.cpp:11:10:注意:候选:void HTTP::get2(const char*,void(*)(const char*))
void get2(常量字符*url,void(*回调)(常量字符*)
^
HttpRequests.cpp:11:10:注意:参数2没有从“test()::”到“void(*)(const char*)”的已知转换

没有捕获列表的lambda与函数指针兼容,因此可以将第一个lambda作为参数传递给
get1()
。但是,带有捕获列表的lambda不能转换为函数指针,因此无法将其传递到
get2()

具有捕获的lambda具有状态,但函数不能具有状态,这就是此类lambda不能转换为函数指针的原因

让函数接受任何lambda(或任何可调用对象)的最常见方法是使用函数模板:

class HTTP {

    // ...

    template <typename Callable>
    void get1(const char* url, void* context, Callable callback)
    {
        callback(context, "");
    }

    template <typename Callable>
    void get2(const char* url, Callable callback)
    {
        callback("");
    }
}
class-HTTP{
// ...
模板
void get1(常量字符*url,void*上下文,可调用回调)
{
回调(上下文“”);
}
模板
void get2(const char*url,可调用回调)
{
回拨(“”);
}
}

作为函数模板,代码大小可能会成为一个问题。如果这是不可接受的,则保留当前函数,并限制自己永远不要传递使用捕获的lambda。

为什么不将
get2
作为可以接受任何可调用对象的函数模板<代码>模板void get2(const char*url,F F){F(“”;}.Nice。。但是,如何通知API用户要使用的必需参数?有了这个(有效的)实现,猜测我需要什么取决于他的工作。@elcuco C++20概念可能会有所帮助,但我想这太晚了,在您的案例中不是一个选项。因此,您只需记录预期的签名。
class HTTP {

    // ...

    template <typename Callable>
    void get1(const char* url, void* context, Callable callback)
    {
        callback(context, "");
    }

    template <typename Callable>
    void get2(const char* url, Callable callback)
    {
        callback("");
    }
}