删除lambda赋值运算符背后的基本原理? 我刚刚了解到C++中的(甚至易变的)lambda是(C.F.Cux:CululyType::运算符=< /COD>)。

删除lambda赋值运算符背后的基本原理? 我刚刚了解到C++中的(甚至易变的)lambda是(C.F.Cux:CululyType::运算符=< /COD>)。,c++,lambda,C++,Lambda,例如: auto x = 0; auto l0 = [copy = x]() mutable {}; auto l1 = []() mutable {}; static_assert(not std::is_copy_assignable_v<decltype(l0)>); static_assert(std::is_copy_assignable_v<decltype(std::ref(x))>); static_assert(std::is_copy_assigna

例如:

auto x = 0;
auto l0 = [copy = x]() mutable {};
auto l1 = []() mutable {};

static_assert(not std::is_copy_assignable_v<decltype(l0)>);
static_assert(std::is_copy_assignable_v<decltype(std::ref(x))>);
static_assert(std::is_copy_assignable_v<decltype(l1)>);
autox=0;
自动l0=[copy=x]()可变{};
自动l1=[]()可变{};
静态断言(非std::is_copy_assert_v);
静态断言(std::is_copy_assert_v);
静态断言(std::is_copy_assert_v);
我在问这个选择背后的理由:为什么要删除
操作符=
?特别是在可能被默认的情况下,即lambda是
可变的
,并且所有捕获本身都是可复制分配的(例如上面示例中的
l0


我知道不可更改的lambdas的相关问题。但我想理解这个决定,而不是围绕它工作。

我怀疑它没有被提出。Lambdas进入的语言比它们喜欢的函数对象弱得多,并且慢慢地恢复了功能。对于特殊的成员函数,建议为无CaptureLambda增加可分配性和默认构造性。R0中只提出了默认的可构造性,因为这是作者需要的,可以说是最明显的缺陷,但R1中基于委员会的反馈提出了可分配性

带有捕获的lambda的默认可构造性当然与语言一致:

auto x1 = [i = 1]() { return i; };
static_assert(not std::is_default_constructible_v<decltype(x1)>); // why??

struct { int i = 1; auto operator()() { return i; } } x2;
static_assert(std::is_default_constructible_v<decltype(x2)>);
但是您不能重新绑定(移动分配到)此
唯一\u ptr
,因为lambda会人工删除分配,即使其捕获状态允许它。将其重写为函数对象类型,并且
unique_ptr
是可赋值的,并为函数对象类型生成赋值运算符


这只是一个示例,但希望它能澄清您是否要分配到捕获状态(std::ref(分配器))与允许调用操作符对捕获状态执行的操作不同。(链接问题的答案是错误的。)

在千层面中可变仅意味着捕获的变量是可变/非常量的,可能是因为每个非空捕获lambda类型都有一个唯一的实例。除了已分配的唯一实例之外,您将为其分配什么?该实例不必是唯一的。例如:
automake(ints){return[x=s]()可变{};}
mutable
影响呼叫操作员;它与成员变量无关,因此不应影响任何特殊的成员函数。
auto allocator_delete(auto& allocator) {
    using traits = typename std::allocator_traits<std::decay_t<decltype(allocator)>>;
    return [alloc=std::ref(allocator)](typename traits::pointer p) { traits::deallocate(alloc, p, 1); };
}
template<class Alloc> using allocator_deleter_t = decltype(allocator_delete(std::declval<Alloc&>()));
static_assert(not std::is_move_assignable_v<std::unique_ptr<int, allocator_deleter_t<std::allocator<int>>>>);
// why??