remove_if的问题
#include<iostream> #include<list> #include<algorithm> #include"PRINT_ELEMENTS.h" using namespace std; class Nth{ private: int nth; int count; public: Nth(int n):nth(n),count(0){ } bool operator()(int){ return ++count==nth; } }; int main(int argc, char **argv) { list<int> coll; for(int i=1; i<=9;++i){ coll.push_back(i); } PRINT_ELEMENTS(coll,"initialized: "); list<int>::iterator pos = remove_if(coll.begin(),coll.end(),Nth(3)); coll.erase(pos, coll.end()); PRINT_ELEMENTS(coll, "remove_if: "); return 0; }
//PRINT_ELEMENTS.h
template<typename T> inline void PRINT_ELEMENTS(const T& coll, const char* optcstr="") { typename T::const_iterator pos; std::cout << optcstr << std::endl; for(pos = coll.begin(); pos != coll.end(); ++pos) std::cout << *pos << " "; std::cout << std::endl; }
输出结果:
initialized: 1 2 3 4 5 6 7 8 9 remove_if: 1 2 4 5 7 8 9
而不是:
initialized: 1 2 3 4 5 6 7 8 9 remove_if: 1 2 4 5 6 7 8 9
此处是remove_if的问题:
remove_if源代码为:
template<typename ForwIter, typename Predicate> ForwIter remove_if(ForwIter beg, ForwIter end, Predicate op) { beg=find_if(beg, end, op) if(beg == end) { return beg; } else { ForwIter next = beg; return remove_copy_if(++next, end, beg, op); } }
这里find_if调用op是复制了一个op的副本,所以当remove_copy_if再次调用op是用重新计数了,所以也把6删除了;
可以用:
#include<iostream> #include<list> #include<algorithm> #include"PRINT_ELEMENTS.h" using namespace std; class Nth{ private: int nth; int count; public: Nth(int n):nth(n),count(0){ } bool operator()(int){ return ++count==nth; } }; template<typename ForwIter, typename Predicate> ForwIter remove_if_my(ForwIter beg, ForwIter end, Predicate op) { while(beg != end && !op(*beg)) { ++beg; } if(beg == end) { return beg; } else { ForwIter next = beg; return remove_copy_if(++next, end, beg, op); } } int main(int argc, char **argv) { list<int> coll; for(int i=1; i<=9;++i){ coll.push_back(i); } PRINT_ELEMENTS(coll,"initialized: "); list<int>::iterator pos = remove_if_my(coll.begin(),coll.end(),Nth(3)); coll.erase(pos, coll.end()); PRINT_ELEMENTS(coll, "remove_if: "); return 0; }
这样避去用find_if,所以就可以了。
参考:《C++标准程序库》P302