list::remove_if(???)

xuechengw 2004-10-12 03:54:26
HI ,

I have create the following code, would you please
give me some suggestions on how to write the parameter
of remove_if(), and the condition I want to use is the
element's flag is false?

----------------------------------------------
class PclElem
{
bool flag;
...
}

typedef list<PclElem*> PclElemList;

PclElemList *pcPclElemList = new PclElemList;

// add element to the list and set the flag for each element
...

// remove the element that the flag is false
pcPclElemList->remove_if(????).
----------------------------------------------

With many thanks!
Bst Rgd!
...全文
268 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
pongba 2004-10-17
  • 打赏
  • 举报
回复
throw away the "not_equal_to", use the solution I gave out initially.
xuechengw 2004-10-15
  • 打赏
  • 举报
回复
Thanks!
I will download and study the boost library, that's a big one for me:(
but without boost library, is there any solution?
pongba 2004-10-14
  • 打赏
  • 举报
回复
class PclElem
{
bool flag;

//add mem function here -- actually,did you already have it?
bool getFlag()
{
return flag;
}
};

vector<PclElem*> vec;//maybe you wanna store "PclElem" instead of "PclElem*" here,too...
std::remove_if(vec.begin(),vec.end(),std::not1(std::mem_fun(&PclElem::getFlag)));

//to take advantage of the enhanced 'mem_fun' of boost,you can use:
std::remove_if(vec.begin(),vec.end(),std::not1(boost::mem_fun(&PclElem::getFlag)));
//this fits all,no matter whether you put PclElem* or PclElem in your container!

--
cheers
Jinhao 2004-10-14
  • 打赏
  • 举报
回复
你把他改成 template<typename _Prl>
demo001 2004-10-14
  • 打赏
  • 举报
回复
mark
Jinhao 2004-10-14
  • 打赏
  • 举报
回复
to xuechengw(红桃k')
typedef binder2nd<not_equal_to<_Ty> > _Pr1; 这是多余的! 应该说是VC6的std lib的BUG
xuechengw 2004-10-14
  • 打赏
  • 举报
回复
The parameter type of *std::list::remove_if* is :
---------------------------------------------
typedef binder2nd<not_equal_to<_Ty> > _Pr1;
---------------------------------------------
Thus the solution you all printed are not suitable
and seems fit to the *std::remove_if* function.

Would you please provide me some other solutions, With
many thank!~
xuechengw 2004-10-14
  • 打赏
  • 举报
回复
TO grooving(向结贴的兄弟们敬礼!) ,
The following compile time error
---------------------------------------------------------
error C2664: 'remove_if' : cannot convert parameter 1 from 'class is_odd<int>' to 'class std::binder2nd<struct std::not_equal_to<int> >'
No constructor could take the source type, or constructor overload resolution was ambiguous
---------------------------------------------------------
xuechengw 2004-10-14
  • 打赏
  • 举报
回复
TO Jinhao(辣子鸡丁)(短歌马甲 No.0)
the following compile time error
-----------------------------------------------------------
error C2664: 'remove_if' : cannot convert parameter 1 from 'class A<class PclElem>' to 'class std::binder2nd<struct std::not_equal_to<class PclElem> >'
No constructor could take the source type, or constructor overload resolution was ambiguous
-----------------------------------------------------------
pongba 2004-10-14
  • 打赏
  • 举报
回复
attention: there's no way to implement an operator != like this:

bool operator != (PclElem const * p1,PclElem const * p2) //compile error
{
p1->flag!=p2->flag;
}

...remove_if(not_equal_to<PclElem*>());

It seems very attractive.But note the concept the code expresses--it changes the semantic of build in operator != of build in pointer type,so stop it,or anyway the compiler will stop it by throw you a compiler error saying that operator != can't be overloaded for buildin types only!
pongba 2004-10-14
  • 打赏
  • 举报
回复
Since I haven't my own notebook at hand which has boost installed,I just give you some "like this" code,check below:

//first,add operator == and operator != to your PclElem since it's comparable
//then include <boost/lambda/lambda.hpp> //or boost/lambda.hpp,somehow I forgot it:-)

using boost::lambda::_1;

//then use this
...remove_if( *_1 != nouse ); //I'll test it when I came back to my notebook

//for now ,wish you good luck:-)
pongba 2004-10-14
  • 打赏
  • 举报
回复
to xuechengw(红桃k'),my buddy,it seems that you've misunderstood something.

First to all,which is most important,is that your not_equal_to<PclElem*>(...) above actually did a *Pointer Comparation*,which of course always yeilds a *false* because no element in the list get the same address with &nose!

And some other things should be known by you:
Since the Type of elements stored here is PclElem* which is a pointer type,using "not_equal_to" naively will always be an error,which occurs at runtime rather than compile time because two pointers can be compared,which is most puzzling!

So,Are there any solutions?There is ,but More complexed than you may think if you wanna go a shortcut.
Anyway I'll show you below.

Rational : There's absolutely no need for a virtual operator() in a predication functor,because the functor is passed as a template type parameter,or have its type deduced ,compiler knows(and should know) what the predication is.

Virtual functions here just add runtime cost.

Be clear that what you face is *template*,which is a *complete* compile-time-thing,so why do we need a oo approach(ie..via virtual functions) since compiler can get(or deduce) the full type information about our Predication functor?

Actually,as you see from the source code of remove_if,it just treat the predication as a static(not dynamic) type and invoke the operator() on it,not via virtual functions!

Review your 'test' class,and find what mistake you've made: you needn't derive your test from "not_equal_to" which isn't for your derivation but for a simplified in-line construction of the simple operator !=.

Have a break,and think it twice,latter i'll show you some solution.
xuechengw 2004-10-14
  • 打赏
  • 举报
回复
Thanks to all!
I have just get a look at the std library(V2.95.3) at
solaris2.8, and found the parameter type of std::list::remove_if
is
---------------------
typedef template <class _Predicate> _Predicate;
---------------------
, which is diffrent from the one that VC6 provided
---------------------
typedef binder2nd<not_equal_to<_Ty> > _Pr1;
---------------------
Thus the solution that Jinhao(辣子鸡丁)(短歌马甲 No.0) provide
is right under the solaris platform. Sorry!

pongba(世界是泛型的...)'s suggestion is just what I am tring
to learn. Thanks!

But as to the problem I have encountered, *the parameter of
std::list::remove_if*.
(1) definition of std::list::remove_if
--------------------------------------------------
typedef binder2nd<not_equal_to<_Ty> > _Pr1;
void remove_if(__Pr1 _Pr)
{iterator _L = end();
for (iterator _F = begin(); _F != _L; )
if (_Pr(*_F))
erase(_F++);
else
++_F; }
--------------------------------------------------
(2)definition of class binder2nd
-----------------------------------------------------------------
template<class _Bfn>
class binder2nd
: public unary_function<_Bfn::first_argument_type,
_Bfn::result_type> {
public:
binder2nd(const _Bfn& _X,
const _Bfn::second_argument_type& _Y)
: op(_X), value(_Y) {}
result_type operator()(const argument_type& _X) const
{return (op(_X, value)); }
protected:
_Bfn op;
_Bfn::second_argument_type value;
};
-----------------------------------------------------------------
(3) definition of struct not_equal_to
-----------------------------------------------------------------
template<class _Ty>
struct not_equal_to : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty& _X, const _Ty& _Y) const
{return (_X != _Y); }
};
-----------------------------------------------------------------
Then my source code is realized as below, but it still dose not
work well, after call remove_if, all of the element have been
removed, but there must be some element with flag is true.
--------------------------------------------------
class test :public not_equal_to<PclElem*>
{
bool operator()(const PclElem* & rhs, const PclElem* &) const
{
return !rhs->flag;
}

};

PclElem nouse;
nouse.flag = true;

pcPclElemList->remove_if(
binder2nd<not_equal_to<PclElem*> >(test(), &nouse));
--------------------------------------------------
I found that in template class not_equal_to, the member
function bool operator()(...) is not a virtual function,
then the class that I have inherited can not override this
function.
If my analysis is right, then how to realize the paremeter
of std::list::remove_if under the MS VC6 enviromnet?
pongba 2004-10-14
  • 打赏
  • 举报
回复
of course,the member cousin of remove_if is more efficient,but that's not the point here,the point is how to build the predicating function (functor).

But anyway,I really made a mistake.
Jinhao 2004-10-14
  • 打赏
  • 举报
回复
i don't know why u don't use std::list<>::remove_if?
it is more efficient!
pongba 2004-10-14
  • 打赏
  • 举报
回复
sorry,I missed <functional> in my code above...
pongba 2004-10-14
  • 打赏
  • 举报
回复
actually,xuechengw,you've asked a pretty good question,some budies just write their functions (or functors) by themselvs,never got a sight that the std header--<functional>--has offered a large amount of facilities for you to express your mind,especially when you compose some functions together.

BTW.It's better to see that boost provides even better(sometimes I would rather say "perfect") facilities for functional programming,ie..enhanced bind ,mem_fun,lambda,So just use them ,you'll find them really amazing!
grooving 2004-10-12
  • 打赏
  • 举报
回复
#include <list>
#include <iostream>

template <class T> class is_odd : public std::unary_function<T, bool>
{
public:
bool operator( ) ( T& val )
{
return ( val % 2 ) == 1;
}
};

int main( )
{
using namespace std;
list <int> c1;
list <int>::iterator c1_Iter, c2_Iter;

c1.push_back( 3 );
c1.push_back( 4 );
c1.push_back( 5 );
c1.push_back( 6 );
c1.push_back( 7 );
c1.push_back( 8 );

cout << "The initial list is c1 =";
for ( c1_Iter = c1.begin( ); c1_Iter != c1.end( ); c1_Iter++ )
cout << " " << *c1_Iter;
cout << endl;

list <int> c2 = c1;
c2.remove_if( is_odd<int>( ) );

cout << "After removing the odd elements, "
<< "the list becomes c2 =";
for ( c2_Iter = c2.begin( ); c2_Iter != c2.end( ); c2_Iter++ )
cout << " " << *c2_Iter;
cout << endl;
}
Jinhao 2004-10-12
  • 打赏
  • 举报
回复
template<typename T>
class A
{
bool flag_;
public:
A(bool flag):flag_(flag)
{}

bool operator()(const T& rhs) const
{
return flag_==rhs.getflag();
}
};

class PclElem
{
bool flag;
public:

bool getflag()const
{ return flag; }
};

int main()
{
list<PclElem> lst;
for(int i=0; i<10; i++)
lst.push_back(PclElem());
cout<<lst.size()<<endl; //输出10
lst.remove_if(A<PclElem>(false));
cout<<lst.size()<<endl; //输出0, 因为stl对所有内建类型的都是以0来初始化,所以10个PclElem实例对象的flag都是false
}

24,860

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧