在 value_type 可移动但不可复制的列表上调用 std::remove_if

Cpp*_*oob 0 c++ gcc c++11

我正在尝试这样的事情:

\n\n
class MyClass\n{\npublic:\n explicit MyClass(int) {...};\n MyClass(MyClass&& that) { swap(that); }\nprivate:\n MyClass(const MyClass&); // disabled, pre-C++11 syntax\n MyClass& operator=(const MyClass&); // disabled, pre-C++11 syntax\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我有一个列表,我通过 emplace 将它们插入其中,我正在尝试做这样的事情。

\n\n
std::list<MyClass> lst;\nstd::remove_if(lst.begin(), lst.end(), [&,this](MyClass& mcl) { return mcl.is_foo();});\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 gcc 4.6.x 上,我不断收到此错误:

\n\n
In file included from /usr/include/c++/4.6/algorithm:63:0,\n             from simple_file_cache.cpp:5:\nfile_cache_entry.h: In function \xe2\x80\x98_FIter std::remove_if(_FIter, _FIter, _Predicate)   \n[with_FIter = std::_List_iterator<MyClass>, _Predicate = \nAnotherClass::foo_bar(std::tuple<unsigned int, unsigned int>)::<lambda(MyClass&)>]\xe2\x80\x99:\nanotherclass.cpp:225:11:   instantiated from here\nanotherclass.h:68:18: error: \xe2\x80\x98MyClass& MyClass::operator=(const MyClass&)\xe2\x80\x99 is private\n/usr/include/c++/4.6/bits/stl_algo.h:1149:13: error: within this context\nmake: *** [simple_file_cache.o] Error 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么要寻找复制构造函数?

\n

dyp*_*dyp 5

您需要为 定义一个移动赋值运算符remove_if。如果存在用户声明的复制赋值运算符(或用户声明的复制构造函数、dtor 或...),则不会隐式声明它。

以下似乎在 g++4.6 下编译:

#include <list>
#include <algorithm>

class MyClass
{
public:
 explicit MyClass(int) {};
 MyClass(MyClass&&) {}
 MyClass& operator=(MyClass&&) {return *this;}
private:
 MyClass(const MyClass&); // disabled, pre-C++11 syntax
 MyClass& operator=(const MyClass&); // disabled, pre-C++11 syntax
};

int main()
{
    std::list<MyClass> lst;

    // compiles, but why use that:
    //std::remove_if(lst.begin(), lst.end(), [](MyClass& mcl) { return true; });

    // also compiles, makes more sense to me (but that depends on the context):
    lst.remove_if([](MyClass& mcl) { return true; });
}
Run Code Online (Sandbox Code Playgroud)

noexcept请注意,如果您能保证的话,您应该考虑同时使用两个 move 函数。

实例


如果您想将列表中的某些元素移动到列表末尾,我宁愿使用基于splice. 例如,

template<class value_type, class allocator, class F>
//typename std::list<value_type, allocator>::iterator
void
move_to_end_if(std::list<value_type, allocator>& list, F condition)
{
    if(list.size() < 2) return; //list.end();

    auto const former_last = std::prev(list.end());

    for(auto i = list.begin(); true; ++i)
    {
        if(condition(*i))
        {
            list.splice(list.end(), list, i);
        }

        if(i == former_last) break;
    }

    // return ????;
}
Run Code Online (Sandbox Code Playgroud)

这会将满足条件的所有元素移动到列表的实际(当前)末尾,并保留它们的相对顺序。

注意:该算法应返回一个迭代器到未移动序列的末尾,或list::end()。还没有找到一种优雅的方法来做到这一点。