Hel*_*ein 2 c++ lambda stl operator-overloading c++11
我有这个代码(简化):
std::vector<Session> sessions;
// ...
std::remove_if( sessions.begin(), sessions.end(),
[] (const Session& s) {
return false;
}
);
Run Code Online (Sandbox Code Playgroud)
当我编译它(在Visual Studio 2013 Update 1中)时,我收到以下错误:
algorithm(1759): error C2280: 'Session &Session::operator =(const Session &)' : attempting to reference a deleted function
Session.h(78) : see declaration of 'Session::operator ='
Run Code Online (Sandbox Code Playgroud)
的确,我operator=在Session课堂上删除了这样的内容:
Session& operator= (const Session& that) = delete;
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么remove_if使用lambda表达式需要赋值运算符?一个Session对象分配给另一个对象在哪里?
更新:正如@nosid和@Praetorian所解释的那样,remove_if需要移动或复制构造函数和赋值运算符.根据C++ 11标准,移动构造函数/赋值运算符应该由编译器自动生成.不幸的是Visual Studio 2013不这样做.由于类不可复制remove_if也无法求助于复制,因此编译器显示错误.我通过手动实现移动构造函数和移动赋值运算符来修复它.
std::remove_if 要求通过解除引用迭代器获得的对象是MoveAssignable(第25.3.8/1节).但是因为你明确地使用delete了复制赋值运算符,所以移动赋值运算符也是隐含的deleted.
假设Session可以支持移动语义,您可以remove_if通过定义移动赋值运算符来开始工作.例如,简单地添加defaulted移动赋值运算符就足以解决当前的问题(请注意,您可能无法依赖于编译器生成的版本,并且可能必须自己定义一个).
Session& operator=(Session&&) = default;
Run Code Online (Sandbox Code Playgroud)
VS2013不支持默认的移动构造函数/赋值运算符,因此在您的情况下,您将被迫实现一个.
该错误不是由lambda表达式引起的.lambda表达式很好,如果你替换remove_if为all_of:
// OK
std::all_of(_sessions.begin(), _sessions.end(),
[](const Session& session) { return false; });
Run Code Online (Sandbox Code Playgroud)
该错误是由算法引起的std::remove_if.通过移动范围内的元素来完成移除,使得不被移除的元素出现在范围的开头.因此,需要复制或移动分配.
对于需要复制或移动赋值操作的其他算法,您将看到相同的错误消息,即使它们在没有lambda表达式的情况下使用也是如此.这是一个例子:
// ERROR: Session& operator=(const Session&) is private
std::move(std::next(_sessions.begin()), _sessions.end(), _sessions.begin());
Run Code Online (Sandbox Code Playgroud)