我想创建一个可以包装任何lambda的函数,以便在其上记录开始/结束调用。
以下代码适用,除了:
具有捕获的任何lambda
任何返回void的lambda(尽管可以通过编写第二个函数轻松修复此问题)
#include <iostream>
#include <functional>
template <class T, class... Inputs>
auto logLambda(T lambda) {
return [&lambda](Inputs...inputs) {
std::cout << "STARTING " << std::endl;
auto result = lambda(inputs...);
std::cout << "END " << std::endl;
return result;
};
}
int main() {
int a = 1;
int b = 2;
// works
auto simple = []() -> int {
std::cout << "Hello" << std::endl; return 1;
};
logLambda(simple)();
// works so long as explicit type is declared
auto with_args = [](int a, int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int, int), int, int>(with_args)(a, b);
// Does not work
// error: no matching function for call to ‘logLambda<int(int), int>(main()::<lambda(int)>&)’
auto with_captures = [&a](int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int), int>(with_captures)(b);
}
有没有办法做到这一点?宏也是可以接受的
答案 0 :(得分:4)
使用Raii来处理void和non-void返回类型,
并按值捕获函子,以避免悬挂参考,
并使用通用lambda避免必须指定您自己的参数
结果类似:
template <class F>
auto logLambda(F f) {
return [f](auto... args) -> decltype(f(args...)) {
struct RAII {
RAII() { std::cout << "STARTING " << std::endl; }
~RAII() { std::cout << "END " << std::endl; }
} raii;
return f(args...);
};
}
通话如下:
const char* hello = "Hello";
logLambda([=](const char* s){ std::cout << hello << " " << s << std::endl; })("world");
答案 1 :(得分:3)
该代码具有未定义的行为。
auto logLambda(T lambda) {
return [&lambda]
您正在通过引用捕获局部参数。