这个问题有两部分
首先,有人可以解释一下 C++ 禁用 lambda 的复制赋值运算符背后的基本原理吗?如果您要允许复制构造函数,为什么不允许复制赋值运算符?
其次,在不强制人们编写 C++03 风格仿函数或使用 std::function(我正在处理的函数很小,而且我希望编译器尽可能内联它们)?
背景: 我正在尝试在 stream processing library I'm writing 中实现类似 flat_map 的操作,类似于 Scala 或其他函数式语言中的 flatMap。因此,我需要创建一个遍历迭代器列表的迭代器。每次取消引用 flat_map 迭代器时,都会执行与内部迭代器关联的 lambda。每次内部迭代器到达末尾时,外部迭代器都需要切换内部迭代器。由于内部迭代器包含一个 lambda,因此没有复制赋值运算符,因此无法切换它。从技术上讲,我可以使用动态分配来解决问题,因此我总是调用复制构造函数,但这似乎不是正确的方法。以下是可能有助于突出问题的代码片段:
template <typename Iter>
class flat_map_iterator {
public:
flat_map_iterator& operator++() {
++it_inner_;
if (it_inner_ == (*it_outer_).end()) {
++it_outer_;
// ERROR: cannot be assigned because its copy assignment operator is implicitly deleted
it_inner_ = (*it_outer_).begin();
}
return *this;
}
private:
Iter it_outer_;
typename Iter::value_type::iterator it_inner_;
};
编辑:
感谢您的快速回复。这是一个用例示例:
int res = ftl::range(1, 4).map([](int a){
return ftl::range(a, 4).map([a](int b){
return std::make_tuple(a, b);
});
})
.flat_map([](std::tuple<int, int> x){ return std::get<0>(x) * std::get<1>(x); })
.sum();
assert(res, 25);
ftl::range(begin, end)
函数在 [begin, end)
范围内返回惰性迭代器。
最佳答案
并不是说 C++ 禁用了 lambda 本身的复制赋值运算符,而是默认情况下,lambda 对象中的成员被保存为 const,然后赋值运算符基本上不能为它们赋值,所以它没有生成。如果您希望 lambda 不将成员保留为 const,您可以使用 [...](...) mutable {...}
语法。
另一件事是,我不完全确定您从分配 lambda 中得到了什么。我的意思是,如果您打算重新使用 lambda 类型(和功能)并将其简单地绑定(bind)到不同的变量,那么您已经在使用很好的 lambda 捕获语法,并且还不如将它作为一个普通的函数对象. 将一种类型的 lambda 分配给另一种类型是不可能的。这意味着当您按值保存 lambda 本身时,您不能提供不同的 lambda 实现。
如果这仍然是您想要的,我认为动态分配(例如使用unique_ptr
)是公平的游戏。
如果你真的想避免它,你可以手动销毁并重新构造你的 lambda,如下所示 example说明:
#include <iostream>
template <class T>
struct LambdaContainer {
LambdaContainer(const T& lambda)
: lambda{lambda} {}
void resetLambda(const T& lambda) {
this->lambda.~T();
new (&this->lambda) T{lambda};
}
T lambda;
};
int main()
{
int i = 1;
auto l = [=]() {
std::cout << i;
};
using LT = decltype(l);
LambdaContainer<LT> lc{l};
lc.resetLambda(l);
}
关于c++ - 在 C++ 中模拟 lambda 的复制赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41379369/