2014-02-16 50 views
0

我想是這樣的remove_if像這樣的東西。調用的std ::名單上,其VALUE_TYPE是可移動的,但不可拷貝

std::list<MyClass> lst; 
std::remove_if(lst.begin(), lst.end(), [&,this](MyClass& mcl) { return mcl.is_foo();}); 

海合會4.6.X,我不斷收到此錯誤:

In file included from /usr/include/c++/4.6/algorithm:63:0, 
      from simple_file_cache.cpp:5: 
file_cache_entry.h: In function ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) 
[with_FIter = std::_List_iterator<MyClass>, _Predicate = 
AnotherClass::foo_bar(std::tuple<unsigned int, unsigned int>)::<lambda(MyClass&)>]’: 
anotherclass.cpp:225:11: instantiated from here 
anotherclass.h:68:18: error: ‘MyClass& MyClass::operator=(const MyClass&)’ is private 
/usr/include/c++/4.6/bits/stl_algo.h:1149:13: error: within this context 
make: *** [simple_file_cache.o] Error 1 

爲什麼它尋找一個拷貝構造函數?

+0

'std :: remove'或'std :: remove_if'?您的標題和您的代碼不匹配。 –

+2

另請注意,GCC 4.6中的C++ 11支持受到嚴重限制。 –

+0

實際上,'std :: list'上的'std :: remove_if'對我沒有這樣的意義。我寧願使用'std :: list :: erase'或'std :: list :: remove_if'。 – dyp

回答

4

您需要爲remove_if定義一個移動賦值運算符。如果存在用戶聲明的複製賦值運算符(或用戶聲明的複製ctor,或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; }); 
} 

注意你應該考慮兩個移動功能noexcept,如果你能保證這一點。

Live example


如果你想在列表的一些元素移到列表的末尾,我寧願使用基於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 ????; 
} 

這使滿足條件的列表的實際(當前)結尾的所有元素,並保持其相對順序。

注意:該算法應該將迭代器返回到未移動序列的末尾,或list::end()。還沒有找到一個優雅的方式來做到這一點。

+0

當然,你需要實現這些功能;) – dyp

+0

也許有可能推廣這種算法。我嘗試使用額外的「目標」迭代器('move_to_if'),但我不確定'end'迭代器是否被'splice'無效。 – dyp

+0

['move_to_end_if'應該被稱爲'stable_list_partition'(與謂詞相反)。](http://coliru.stacked-crooked。com/a/c9992ebafebc4c72)我同意它應該返回分區點以符合['std :: stable_partition'](http://en.cppreference.com/w/cpp/algorithm/stable_partition)。很好'stable_list_partition'爲沒有'std :: stable_partition'的附加存儲需求的N個項目列表執行O(N)拼接以獲得複雜性保證。 – Casey

相關問題