gpt4 book ai didi

c++ - 删除 lambda 赋值运算符的基本原理?

转载 作者:行者123 更新时间:2023-12-03 23:41:54 24 4
gpt4 key购买 nike

我刚刚了解到 C++ 中的(甚至 mutable )lambda 是 not assignable unless it has empty captures (参见 ClosureType::operator=)。
例子:

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)>);
我在问这个选择背后的理由:为什么 operator=删除?特别是在可能默认的情况下,即 lambda 为 mutable并且所有捕获本身都是可复制分配的(例如上面示例中的 l0)?
我知道 thismutable 的相关问题 lambda 斯。但我想了解这个决定而不是解决它。

最佳答案

我怀疑它没有被提议。 Lambda 进入语言时比它们作为糖的函数对象要弱得多,并且正在慢慢恢复功能。关于特殊成员函数,P0624建议为无捕获 lambda 添加可分配性和默认可构造性。在 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)>);
可分配性也是一致且有用的。只是想到的一个例子,在某个时候有人提议有一个 std::default_delete 的类似物。对于分配器,即可以用作 std::unique_ptr 的模板参数的类型对于分配器分配的指针。您可以想象使用 lambda 来捕获分配器并将其用于这样的目的:
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??
但是你不能重新绑定(bind)(移动分配到)这个 unique_ptr ,因为 lambda 人为地删除了分配,即使它的捕获状态允许它。将其重写为函数对象类型和 unique_ptr是可赋值的,为函数对象类型生成赋值运算符。
这只是一个示例,但希望它澄清您是否要分配给捕获状态( std::ref(allocator))与允许调用运算符(operator)对捕获状态执行的操作不同。 (链接问题的答案是错误的。)

关于c++ - 删除 lambda 赋值运算符的基本原理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65275712/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com