【问题标题】:How can I instantiate a lambda closure type in C++11/14?如何在 C++11/14 中实例化 lambda 闭包类型?
【发布时间】:2019-10-17 19:46:47
【问题描述】:

我是aware,lambda 闭包类型没有默认构造函数。但这是否意味着它作为模板参数传递后就无法实例化?

考虑以下minimal example

#include <iostream>

template <typename FuncType>
std::pair<int,int> DoSomething() {
    return FuncType()(std::make_pair(1,1));
}

int main() {
    auto myLambda = [](std::pair<int,int> x) {
        return std::make_pair(x.first*2,x.second*2);
    };
    std::pair<int,int> res = DoSomething<decltype(myLambda)>();
    return 0;
}

出于性能原因,I can't use std::function 以避免虚拟指针调用。有没有办法做到这一点?我需要实例化该 lambda 一次并在该函数中多次使用它。

decltype(myLambda) 被传递给模板参数中的std::map 比较器时,标准库如何使其工作?

【问题讨论】:

  • 对于带有operator() 的匿名类来说,lambda 主要是语法糖。使用您自己的实现 lambda 的 operator() 声明您自己的命名类。
  • @SamVarshavchik 我希望不必限制用户使用 lambda。我希望它就像我提到的标准库示例一样。
  • 我不知道“用户”是什么意思。这个now looks to be like a definite XY problem。也许你应该试着问你真正的问题是什么。不,不是您在这里写的那个,而是您认为答案的真正问题是以这种方式使用 lambda,这就是您要问的问题。也许对于你的真正问题有一个完全不同的解决方案,但不知道它是什么,没有人能帮助你。
  • 我觉得我这里有什么不明白的地方。为什么不将 lambda 作为函数参数传递并多次调用?

标签: c++ performance lambda closures c++14


【解决方案1】:

虽然这个特性是在 C++20 中出现的(参见 songyuanyao 的回答),但在这种情况下你实际上并不需要它。您可以将 lambda 作为 FuncType 类型的函数参数传递并多次调用:

template <typename FuncType>
std::pair<int,int> DoSomething(FuncType f)
{
    return f(std::make_pair(1,1));
}

int main()
{
    auto myLambda = [](std::pair<int,int> x) {
        return std::make_pair(x.first*2,x.second*2);
    };
    std::pair<int,int> res = DoSomething(myLambda);
}

【讨论】:

    【解决方案2】:

    我知道 lambda 闭包类型没有默认构造函数。

    是的,在 C++20 之前都是如此。 (注意,由于 C++20 如果没有指定捕获,closure type 有一个默认的默认构造函数。)

    闭包类型不是 DefaultConstructible。闭包类型有 a deleted (until C++14) no (since C++14) 默认构造函数。 (直到 C++20)

    decltype(myLambda) 被传递给模板参数中的std::map 比较器时,标准库如何使其工作?

    标准库没有什么特别之处。如果为std::map 指定一个非DefaultConstructible lambda 作为比较器类型,则必须将一个对象传递给构造函数,std::map 将通过副本初始化其比较器; lambda 具有复制和移动构造函数。

    您可以将代码更改为与std::map's constructor相同的方式:

    template <typename FuncType>
    std::pair<int,int> DoSomething(const FuncType& f = FuncType()) {
        // auto z(f);   // you can take a copy if necessary
        return f(std::make_pair(1,1));
    }
    

    然后

    auto myLambda = [](std::pair<int,int> x) {
        return std::make_pair(x.first*2,x.second*2);
    };
    std::pair<int,int> res = DoSomething<decltype(myLambda)>(myLambda);
    

    LIVE

    【讨论】:

      【解决方案3】:

      正如其他人指出的那样,空 lambdas 将在 C++20 中成为默认可构造的。

      你不能等待/切换到它?
      没问题,它很容易被模拟,只要你的 lambda 不是通用的。

      只需将 lambda 转换为函数指针,然后将其打包成 std::integral_constant

      template <class T>
      constexpr auto make_constant(T t) noexcept
      -> std::integral_constant<decltype(+t), +t>
      { return {}; }
      

      当然,在大多数情况下你可以选择function-objects类型,你也可以传递初始值,这样更容易一些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        • 2018-12-19
        • 2020-05-01
        • 2014-12-28
        • 2023-03-19
        • 2015-02-24
        • 2016-06-27
        相关资源
        最近更新 更多