【问题标题】:Possible to store templated lambda into std::function?可以将模板化的 lambda 存储到 std::function 中吗?
【发布时间】:2019-10-03 19:31:07
【问题描述】:

使用 C++20,我们可以使用模板化 lambda 来执行以下操作:

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

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

是否可以将模板化的 lambda 存储到 std::function&lt;&gt; 包装器中?例如类似以下?

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

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

【问题讨论】:

  • 您要解决的实际问题是什么?请注意,通用 lambda 在 C++20 中并不是新的,我们从 C++14 开始就有了它们,只是特定的拼写是新的。
  • auto 不是一个“模板化”的 lambda?喜欢auto t = [](auto tmp){std::cout &lt;&lt; tmp &lt;&lt; std::endl;};
  • 我想将 lambda 作为非静态成员添加到类中。因此,它不能用 auto 定义。
  • 无法抓住重点! “但如果我需要指定确切的类型怎么办?” lambda/函数调用的参数的确切类型?如果是这样,为什么我们在 lambda 定义中需要一个模板/自动?
  • 我不想说auto t = templated lambda。相反,我想说std::function&lt;...&gt; = templated lambda

标签: c++ c++20


【解决方案1】:

模板化的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;};

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

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

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


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

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

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

但只会调用 lambda 的 int 版本。

要求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");

【讨论】:

  • 是的,谢谢你的回答,我会做类似的事情。我只是想确定是否有我没有考虑过的事情。
猜你喜欢
  • 2020-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2016-05-28
相关资源
最近更新 更多