为什么要在 C++ lambda 前面放置一元加号 (+) 运算符?
Why would one want to put a unary plus (+) operator in front of a C++ lambda?
我发现在 C++ 中我们可以在 lambda 函数 +[]{}
中使用 +
文章示例:
#include <iostream>
#include <type_traits>
int main()
{
auto funcPtr = +[] {};
static_assert(std::is_same<decltype(funcPtr), void (*)()>::value);
}
lambda中+符号的主要思想
You can force the compiler to generate lambda as a function pointer rather than closure by adding + in front of it as above.
但是在 lambda 中使用“+”有什么好处呢?你能举个例子或者link我来解释一下吗?
这不是lambda的特性,更多的是隐式类型转换的特性。
那里发生的事情源于这样一个事实,即无捕获的 lambda 可以 隐式转换为指向与 lambda operator()
具有相同签名的函数的指针。 +[]{}
是一个表达式,其中一元 +
是一个 no-op ,所以表达式的唯一合法结果是指向函数的指针。
结果 auto funcPtr
将是指向函数的指针,而不是 lambda 表达式返回的具有匿名类型的对象的实例。在提供的代码中没有太大优势,但它在类型不可知的代码中可能很重要,例如其中使用了某种 decltype
表达式。例如
#include <type_traits>
void foo(int);
template<class T>
struct is_foo : std::is_same<T, decltype(&foo)> {};
int main()
{
auto foo1 = +[](int)->void {};
auto foo2 = [](int)->void {};
static_assert(is_foo<decltype(foo1)>::value, "foo1 is not like foo");
static_assert(is_foo<decltype(+foo2)>::value, "+foo2 is not like foo");
static_assert(is_foo<decltype(foo2)>::value, "foo2 is not like foo");
}
请注意,您可以对 foo
执行相同的操作:std::is_same<T, decltype(+foo)> {};
虽然有些平台可能不支持,因为它们天生就可能有各种调用约定不同的函数指针,表达式会产生歧义。
在模板中针对 lambda 使用函数指针的一个优点可能是减少模板实例化的数量。
template <typename F>
void f(F func) { func(); }
int main()
{
f([](){}); // f<lambda_1>
f([](){}); // f<lambda_2>
f(+[](){}); // f<void(*)()>
f(+[](){}); // f<void(*)()>
}
我发现在 C++ 中我们可以在 lambda 函数 +[]{}
中使用 +
文章示例:
#include <iostream>
#include <type_traits>
int main()
{
auto funcPtr = +[] {};
static_assert(std::is_same<decltype(funcPtr), void (*)()>::value);
}
lambda中+符号的主要思想
You can force the compiler to generate lambda as a function pointer rather than closure by adding + in front of it as above.
但是在 lambda 中使用“+”有什么好处呢?你能举个例子或者link我来解释一下吗?
这不是lambda的特性,更多的是隐式类型转换的特性。
那里发生的事情源于这样一个事实,即无捕获的 lambda 可以 隐式转换为指向与 lambda operator()
具有相同签名的函数的指针。 +[]{}
是一个表达式,其中一元 +
是一个 no-op ,所以表达式的唯一合法结果是指向函数的指针。
结果 auto funcPtr
将是指向函数的指针,而不是 lambda 表达式返回的具有匿名类型的对象的实例。在提供的代码中没有太大优势,但它在类型不可知的代码中可能很重要,例如其中使用了某种 decltype
表达式。例如
#include <type_traits>
void foo(int);
template<class T>
struct is_foo : std::is_same<T, decltype(&foo)> {};
int main()
{
auto foo1 = +[](int)->void {};
auto foo2 = [](int)->void {};
static_assert(is_foo<decltype(foo1)>::value, "foo1 is not like foo");
static_assert(is_foo<decltype(+foo2)>::value, "+foo2 is not like foo");
static_assert(is_foo<decltype(foo2)>::value, "foo2 is not like foo");
}
请注意,您可以对 foo
执行相同的操作:std::is_same<T, decltype(+foo)> {};
虽然有些平台可能不支持,因为它们天生就可能有各种调用约定不同的函数指针,表达式会产生歧义。
在模板中针对 lambda 使用函数指针的一个优点可能是减少模板实例化的数量。
template <typename F>
void f(F func) { func(); }
int main()
{
f([](){}); // f<lambda_1>
f([](){}); // f<lambda_2>
f(+[](){}); // f<void(*)()>
f(+[](){}); // f<void(*)()>
}