【问题标题】:What happens when a type containing a lambda gets assigned?当一个包含 lambda 的类型被赋值时会发生什么?
【发布时间】:2011-12-13 06:00:10
【问题描述】:

假设我有某种类型封装了一个函数,可能是一个 lambda 函数:

template<typename Function>
  struct my_struct
{
  Function f;

  my_struct(const Function &f) : f(f) {}
};

分配此类型的实例时会发生什么?我的理解是 lambda 是不可变的,并且删除了赋值运算符。

然而,当我在下面的代码 sn-p 中将这种类型分配给对象时,不会发出错误:

// a structure which contains a function;
// possibly a lambda function
template<typename Function>
  struct my_struct
{
  Function f;

  my_struct(const Function &f) : f(f) {}

  // XXX adding this assignment operator causes an error
  //my_struct &operator=(const my_struct &other)
  //{
  //  f = other.f;
  //  return *this;
  //}
};

template<typename Function>
my_struct<Function> make_struct(const Function &f)
{
  return my_struct<Function>(f);
}

int main()
{
  // create some lambda
  auto lambda = [](int x){return x;};

  // make a struct containing a copy of the lambda
  auto x = make_struct(lambda);

  // try to assign to the struct, which
  // presumably assigns to the enclosed lambda
  x = make_struct(lambda);

  return 0;
}

添加注释掉的赋值运算符会产生错误,正如预期的那样:

$ g++-4.6 -std=c++0x test.cpp
test.cpp: In member function ‘my_struct<Function>& my_struct<Function>::operator=(const my_struct<Function>&) [with Function = main()::<lambda(int)>, my_struct<Function> = my_struct<main()::<lambda(int)> >]’:
test.cpp:34:25:   instantiated from here
test.cpp:13:5: error: use of deleted function ‘main()::<lambda(int)>& main()::<lambda(int)>::operator=(const main()::<lambda(int)>&)’
test.cpp:27:18: error: a lambda closure type has a deleted copy assignment operator

那么,是否可以使用 lambda 成员变量创建可赋值类型?这似乎是一个合理的尝试。例如,考虑将 lambda 与 boost::transform_iterator 结合使用。

【问题讨论】:

  • 我对搬家还不是很了解,但有没有可能他们可以搬家但不能复制?你可能已经知道了这个问题的答案,但我对 move-ctors 并不了解,所以如果你知道,请告诉。
  • 感谢您的想法,但引入移动运算符似乎并没有改变错误消息。

标签: c++ lambda


【解决方案1】:

你已经接近了。 lambda 具有隐式复制构造函数,并且可能具有(取决于捕获的值)隐式移动构造函数。它有一个已删除的复制赋值运算符。

换句话说,你可以构造它,但你不能分配它。如果你正在寻找一个通用函数对象,你想使用std::function&lt;&gt;。它将函数模拟为一等值。


请注意,不可变与可分配不同。当一个 lambda 被称为 mutable 时,这意味着它的函数调用体可以修改 lambda 的成员(即,该函数不是const):

int i = 0;

auto okay = [=](int x) mutable { i += x; };
auto error = [=](int x) { i += x; };

其中每一个都是可复制构造且不可分配的。

【讨论】:

  • 感谢您的解释。删除分配太糟糕了——它似乎使 lambda 与boost::transform_iterator 不兼容,至少与它当前的实现不兼容。
  • 请参阅this answer 了解其他解决方法(使用 std::ref、建议的 Boost Fit 库和建议的 Boost Range Extensions 库)。
  • 但是 std::function 怎么能复制 lambda 呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
相关资源
最近更新 更多