将 lambda 表达式传递给 lambda 参数 c++11
Pass lambda expression to lambda argument c++11
我想做这样的事情:
int main()
{
auto f = [/*some variables*/](/*take lambda function*/)
{/*something with lambda function*/};
f([/*other variables*/](/*variables to be decided by f()*/)
{/*something with variables*/});
}
我知道可以将 lambda 传递给函数以及 lambda。以下作品:
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f([](int i) -> double
{return 0.0;});
}
但是以下内容不起作用(一旦我更改范围变量以添加 [x](
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;}
f([x](int i) -> double //[x] does not work
{return 0.0;});
}
这给出了错误:
error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
argument types are: (lambda [](int)->double)
object type is: lambda [](double (*)(int))->double
有人会知道如何解决这个问题或解决方法吗?我正在使用英特尔编译器ICPC (ICC( 13.1.2,std=C++11
谢谢
关于您的问题,有几件事需要澄清。第一个是什么是lambda?
lambda 表达式是一个简单的表达式,编译器将从中生成无法命名的唯一类型,同时它将生成该类型的实例。当你编写: [](int i) { std::cout << i; }
编译器将为你生成一个大致为:
struct __lambda_unique_name {
void operator()(int i) const { std::cout << i; }
};
如您所见,它不是一个函数,而是一个将operator()
实现为 const
成员函数的类型。如果 lambda 执行任何捕获,编译器将生成代码来捕获值/引用。
作为极端情况,对于像上面这样的 lambda,其中没有捕获状态,该语言允许从 lambda 类型转换为带有operator()
签名(减去this
部分(的函数指针,因此上面的 lambda 可以隐式转换为指向函数的指针,该函数获取int
并且不返回任何内容:
void (*f)(int) = [](int i) { std::cout << i; }
既然已经说明了基础知识,那么在您的代码中,您有以下 lambda:
auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};
函数参数的规则(也适用于 lambda(确定参数不能是函数类型,因此 lambda 的参数衰减到指向函数的指针(与数组类型的参数衰减为指针类型的方式相同(:
auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};
稍后,您将尝试传递具有捕获作为参数的 lambda。由于存在捕获,因此特殊规则不适用,并且 lambda 不可转换为指向函数的指针,从而产生您看到的编译器错误。
在当前标准中,您可以采用以下两种方式之一。您可以使用类型擦除从签名中删除可调用实体的确切类型:
auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};
由于可以使用具有适当签名的任何可调用实体初始化std::function<double(int)>
,因此这将接受以下代码中的 lambda,但代价是类型擦除,这通常意味着动态分配和动态调度。
或者,您可以删除语法糖并手动滚动第一个 lambda 等效项,但使其通用。在这种情况下,如果 lambda 很简单,这可能是一个有效的选项:
struct mylambda {
template <typename F>
double operator()(F fn) const {
fn(0); return 0.0;
}
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});
最后,如果你有足够的耐心,你可以等待 C++14,在那里(很可能,它还没有被批准(将支持多态 lambda,这简化了上述类的创建:
auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above
尝试使用 std::function:
#include <functional>
int main()
{
int x=0;
int y=0;
auto f = [x,y](std::function<double(int)> func) -> double
{func(0); return 0.0;};
f([x](int i) -> double {return 0.0;});
}
您可能必须像我们在黑暗时代所做的那样简单地咬紧牙关并实现自己的函子:
struct F {
int x;
int y;
F(int x_, int y_) : x(x_), y(y_) {}
template <typename G>
double operator() (G&& g) const {
g(0);
return 0.0;
}
};
#include <iostream>
int main()
{
int x = 0;
int y = 0;
auto f = F(x, y);
f([x](int i){return 0.0;});
f([](int i){std::cout << i << std::endl;});
}
这应该会让你继续前进,直到你的编译器支持 C++14 个通用 lambda。
,如果您事先知道 lambda 的类型,您可以尝试如下操作:
int main()
{
int x = 0, y = 0;
auto f = [x]( int i )->double {
return (double)x;
};
auto f2 = [x,y]( decltype(f) func )->double {
return func( 0 );
};
f2( f );
return 0;
}
或者,您可以使用<functional>
库进行更通用的解决方案,例如:
auto f = [x,y]( std::function<double(int)> func ) { /* Do stuff */ };
您可以引用捕获的 lambda,但此解决方案有其局限性:
#include <new>
#include <utility>
namespace
{
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
std::declval<F>()(std::declval<A>()...))))
{
static L l_(std::forward<L>(l));
static bool full;
if (full)
{
l_.~L();
new (static_cast<void*>(&l_)) L(std::forward<L>(l));
}
else
{
full = true;
}
return [](A... args) noexcept(noexcept(
std::declval<F>()(std::forward<A>(args)...))) -> R
{
return l_(std::forward<A>(args)...);
};
}
}
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
return cify<F, I>(std::forward<L>(l), F());
}
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f(cify<double(*)(int i)>([x](int i) -> double //works now
{return 0.0;}));
}
单击查看工作示例。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 使用自动推导的 lambda 参数作为常量表达式
- 如何参数化用作另一个 lambda 参数的 lambda
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 从成员函数签名中自动推导lambda参数
- Clang声称通用lambda参数的constexpr成员不是constexpr
- 如果我的模板类型首先以lambda参数而发生,则MSVC会引起一个奇怪的错误
- 继承类中没有匹配的泛型委托作为 lambda 参数
- 为什么在lambda参数中不允许自动
- 如何定义通用 lambda 参数的模板参数?
- 在 QGraphicsScene 中拖动 QPixmap:如何避免 lambda 参数中不允许'auto'
- variadic模板函数会以相反的顺序调用lambda参数
- 可变模板lambda参数的模板推导
- 嵌套模板功能中的C 0x lambda参数
- 带有 std::函数和 lambda 参数的分段错误
- 从值捕获的变量分配到lambda参数时,GCC编译器分割故障
- 标准::p空气的通用 lambda 参数
- C++ lambda 参数列表
- 我的 lambda 参数真的在阴影我的当地人吗?
- 从常量和引用的角度来看,函数应该如何接受*lambda*参数