C++ lambda 回调
C++ lambda callbacks
我正在尝试制作一个 HTTP class,我想通过 lambda 使用 C++11(还不是 C++14)回调。我有 2 个可用的模型,第一个有效……但看起来很丑。我的目标是第二个,不是编译(最后出错)。
我无法使用 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);
});
}
gcc 错误 (xtensa-esp32-elf-g++ (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a) 5.2.0)
HttpRequests.cpp: In function 'void test()':
HttpRequests.cpp:29:6: error: no matching function for call to 'HTTP::get2(const char [18], test()::<lambda(const char*)>)'
});
^
HttpRequests.cpp:11:10: note: candidate: void HTTP::get2(const char*, void (*)(const char*))
void get2(const char* url, void (*callback)(const char*) )
^
HttpRequests.cpp:11:10: note: no known conversion for argument 2 from 'test()::<lambda(const char*)>' to '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("");
}
}
作为函数模板,代码大小可能会成为一个问题。如果这不可接受,那么请保留您当前的功能并限制自己永远不要传递使用捕获的 lambda。
我正在尝试制作一个 HTTP class,我想通过 lambda 使用 C++11(还不是 C++14)回调。我有 2 个可用的模型,第一个有效……但看起来很丑。我的目标是第二个,不是编译(最后出错)。
我无法使用 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);
});
}
gcc 错误 (xtensa-esp32-elf-g++ (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a) 5.2.0)
HttpRequests.cpp: In function 'void test()':
HttpRequests.cpp:29:6: error: no matching function for call to 'HTTP::get2(const char [18], test()::<lambda(const char*)>)'
});
^
HttpRequests.cpp:11:10: note: candidate: void HTTP::get2(const char*, void (*)(const char*))
void get2(const char* url, void (*callback)(const char*) )
^
HttpRequests.cpp:11:10: note: no known conversion for argument 2 from 'test()::<lambda(const char*)>' to '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("");
}
}
作为函数模板,代码大小可能会成为一个问题。如果这不可接受,那么请保留您当前的功能并限制自己永远不要传递使用捕获的 lambda。