繁体   English   中英

如何在C ++ 11/14中实例化lambda闭包类型?

[英]How can I instantiate a lambda closure type in C++11/14?

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

请考虑以下最小示例

#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;
}

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

decltype(myLambda)传递给模板参数中的std::map comparators之类的东西时,标准库如何使它工作?

虽然这个功能将在C ++ 20中出现(参见songyuanyao的回答),但在这种情况下你实际上并不需要。 您可以将lambda作为FuncType类型的函数参数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);
}

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

是的,直到C ++ 20才是这样。 (注意,由于C ++ 20没有指定捕获,因此闭包类型具有默认的默认构造函数。)

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

decltype(myLambda)传递给模板参数中的std::map comparators之类的东西时,标准库如何使它工作?

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

您可以将代码更改为与std::map的构造函数相同的方式:

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);

生活

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

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

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

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

当然,在大多数可以选择函数对象类型的情况下,您也可以传递初始值,这样更容易一些。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM