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

C++11 Change `auto` Lambda to a different Lambda?

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

auto a = [] { return true; };

我希望稍后 a 到 return 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 的知识。谢谢。

每个 lambda 表达式都会创建一个新的唯一类型,因此您的第一个 lambda 的类型与您的第二个 (example). Additionally the copy-assignment operator of a lambda is defined as deleted (example) 的类型不同,因此您无法做到这一点。为了达到类似的效果,您可以让 a 成为一个 std::function 对象,尽管它会花费您一些性能

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

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

+[]{return true;}

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

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

在你的情况下,

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 将在赋值时转换为函数指针类型。不过,我喜欢这种一致性。

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

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

我们可以使用 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; });

由于 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; };

这对于更复杂的签名以及推导的 return 类型更方便。