C ++ 11将`auto` Lambda更改为不同的Lambda?

Posted

技术标签:

【中文标题】C ++ 11将`auto` Lambda更改为不同的Lambda?【英文标题】:C++11 Change `auto` Lambda to a different Lambda? 【发布时间】:2016-12-01 23:24:45 【问题描述】:

假设我有以下包含 lambda 的变量:

auto a = []  return true; ;

我希望 a 稍后返回 false。我可以按照这个思路做点什么吗?

a = []  return false; ;

这种语法给了我以下错误:

binary '=' : no operator found which takes a right-hand operand of type 
'main::<lambda_a7185966f92d197a64e4878ceff8af4a>' (or there is no acceptable conversion)

IntelliSense: no operator "=" matches these operands
        operand types are: lambda []bool ()->bool = lambda []bool ()->bool

有没有办法实现这样的目标?我想将 auto 变量更改为不同的 lambda。我是一个初学者,所以我可能缺少一些关于 auto 或 lambdas 的知识。谢谢。

【问题讨论】:

bool b = true; auto a = [&amp;b] return b; ; b = false; 解决方案,但这当然不能适用于所有情况。 【参考方案1】:

每个 lambda 表达式都会创建一个新的唯一类型,因此您的第一个 lambda 的类型与您的第二个 (example) 的类型不同。此外,lambda 的复制赋值运算符被定义为已删除 (example),因此您无法做到这一点。对于类似的效果,您可以将 a 设置为 std::function 对象,尽管这会降低您的性能

std::function<bool()> a = []  return true; ;
a = []  return false; ;

【讨论】:

【参考方案2】:

可以使用一元 + 运算符将 Lambda 转换为函数指针,如下所示:

+[]return true;

只要捕获组为空且没有auto 参数。1

如果你这样做,你可以将不同的 lambdas 分配给同一个变量,只要 lambdas 都具有相同的签名。

在你的情况下,

auto a = +[]return true;;
a = +[]return false;;

Live example on Coliru

将按照您的预期进行编译和操作。2您可以像使用 lambda 一样使用函数指针,因为两者都将充当 functors


1.在 C++14 中,您可以使用 auto 作为参数类型声明 lambda,例如 [](auto t)。这些是generic lambdas,并有一个模板化的operator()。由于函数指针不能表示模板函数,+ 技巧不适用于泛型 lambda。

2。从技术上讲,您不需要分配的第二个 + 运算符。 lambda 将在赋值时转换为函数指针类型。不过,我喜欢这种一致性。

【讨论】:

C++正式进入Perl领域的那一刻! @jaggedSpire 我非常需要这个很多次,我认为唯一的解决方案是另一个function 对这个问题的回答。你是怎么知道的?我以前从未见过。 @JonathanMee 我实际上是从侧边栏中的相关链接中找到的,曾几何时:A positive lambda: +[] - What sorcery is this?【参考方案3】:

每个 lambda 都有不同的类型,因此您无法更改它。您可以使用std::function 来保存任意可调用对象,可以随意更改。

std::function <bool ()> a = []  return true; ;
a = []  return false; ;

【讨论】:

我猜 Ryan 在发布同样的内容时击败了你。但是你少了一个分号。【参考方案4】:

我们可以使用retrospective call 将 lambda 转换为 std::function:

template<typename T>
struct memfun_type

  using type = void;
;

template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>

  using type = std::function<Ret(Args...)>;
;

template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
 // Function from lambda !
  return func;

之后我们就可以做(因为 'a' 现在是 std::function 类型):

auto a = FFL([]  return false; );
a = FFL([]  return true; );

【讨论】:

再解释一下就好了。【参考方案5】:

由于C++17,您可以通过Class template argument deduction 推导出std::function 模板参数。它甚至可以用于捕获 lambda:

int a = 24;

std::function f = [&a] (int p)  return p + a; ;
f               = [&a] (int p)  return p - a; ;
f               = []   (int p)  return p; ;

这对更复杂的签名非常有用,对于推导的返回类型更有用。

【讨论】:

以上是关于C ++ 11将`auto` Lambda更改为不同的Lambda?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用jQuery慢慢将css属性更改为auto?

C++ auto_ptr 和 shared_ptr 从 VC++10 更改为 VC++12

如何将以下代码更改为 lambda 方法参考

C中的MCrypt,为啥加密不将明文更改为哈希/加密数据?

将 Lambda 运行时从 Node 8.x 更改为 Node 12.x 后,从 AWS API Gateway 随机获得 502 Bad Gateway 响应

如何将“-”更改为刽子手(C)的字母?