【问题标题】:c++: Use templates to wrap any lambda inside another lambdac ++:使用模板将任何lambda包装在另一个lambda中
【发布时间】:2019-06-05 13:38:49
【问题描述】:

我想创建一个可以包装任何 lambda 以记录开始/结束调用的函数。

下面的代码可以工作,除了:

  1. 任何具有捕获功能的 lambda

  2. 任何返回 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);

}

有没有办法做到这一点?宏也可以接受

【问题讨论】:

  • 您收到代码错误?请在问题中包含它
  • 你想重塑std::function吗?
  • 你的代码有UB。您通过引用捕获函数局部变量lambda 并将其返回。而是按值捕获。

标签: c++ templates lambda


【解决方案1】:

使用 Raii 处理 void 和非 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");

Demo

【讨论】:

    【解决方案2】:

    该代码具有未定义的行为。

    auto logLambda(T lambda) {
        return [&lambda]
    

    您正在通过引用捕获本地参数。

    【讨论】:

    • 引用捕获有什么问题?这不是 lambdas 的重点吗?
    • @mdsimmo 请阅读整个声明:“您正在通过引用捕获 本地参数。” (强调我的)
    • @mdsimmo 您正在返回对函数局部变量的引用。该变量 dies 在函数末尾,因此访问引用是未定义的行为。
    猜你喜欢
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 2023-03-14
    • 2019-12-15
    • 2018-12-17
    • 2022-06-12
    相关资源
    最近更新 更多