可以将模板化的 lambda 存储到 std::function 中吗?

Possible to store templated lambda into std::function?

在 C++20 中,我们得到模板化的 lambda 来做这样的事情:

    auto t = []<typename T>(T tmp){std::cout << tmp << std::endl;};

但是如果我需要通过 std::function<> 指定确切的类型怎么办? (不要依赖自动)。

是否可以将模板化的 lambda 存储到 std::function<> 包装器中?例如类似于以下内容?

    template<typename T>
    std::function<void(T)>  t = []<typename T>(T tmp){std::cout << tmp << std::endl;};

并像常规模板函数一样使用它?

模板化 std::function 有问题。不是一个std::function,而是多个。当您使用更多类型时,编译器将创建越来越多的全局数据。

此外,模板参数推导将不起作用,因为 std::function 变量是模板化的,而不是 std::functionoperator()

此外,你不需要 C++20 也会有这个问题,用 C++14 试试这个:

// equivalent to the templated lambda, just different syntax
auto t = [](auto tmp){std::cout << tmp << std::endl;};

But what if I need to specify the exact type via std::function<>? (don't rely on auto).

问题是每个 lambda 都有一个无法写入的未命名的唯一类型。 auto唯一 创建 lambda 类型变量的方法。

仅当您需要类型擦除,当您需要未知类型但已知接口的变量(如 operator())时,才使用 std::functionstd::function 不是免费的 并且具有 运行时 二进制大小 成本。它是可调用类型的类型擦除包装器。


如果您真的需要 std::function 怎么办?

嗯,std::function只能处理已知类型。例如,这将起作用:

std::function<void(int)> t = []<typename T>(T arg) { /* ... */ }; 

但只会调用 int 版本的 lambda。

要求 std::function 有一个模板 operator() 就像要求一个虚拟模板函数。无法实现。


如果您想使用名称已知的类型怎么办?

那就不要使用 lambda 表达式!它们可能不是您需要的工具!

这是不使用 auto 或 std::function 的等价物:

struct MyLambda {
    template<typename T>
    auto operator()(T arg) { /* ... */ }
};

MyLambda my_function_returning_lambda() {
    // ...
}

// ...

MyLambda lambda = my_function_returning_lambda();

lambda(1);
lambda("works");