STL remove_if

Started by
14 comments, last by Kyo 20 years, 11 months ago
class CData { ... int value; } now if I have a list of CData how do I use remove_if to only remove data with a certain value? The problem is that the whole adaptable functors bind2nd compose2 and whatnot explanations from sgi''s STL site are about as helpful as a book in egyptian hieroglyphs and all I want to do is remove unique objects in a list, so I can''t use remove(). And the problem with a function object is you don''t instantiate it as far as I can tell, you just pass it like remove_if(functor()) so I can''t tell it what value to compare with to return true. And assuming the value to compare with is 3 the following still doesn''t compile:
  
struct isEqualToValue : public unary_function<data, bool> 
{
	bool operator() (data &rhs) { if (rhs.myValue == 3) { return true; } else { return false; } }
};

L.remove_if(isEqualToValue());
  
Thanks for reading through (and hopefully enlightening me with a reply )
Advertisement
well, that code looks fine on an initial read (though there''s a way to bind "3" to the functor at runtime... pass it into the constructor). What error(s) are you getting?

How appropriate. You fight like a cow.
It''s possible to do list.remove(isEqualToValue(3))?

The error is:


  C:\Program Files\Microsoft Visual Studio\VC98\My Projects\Tests\Linked Lists\Main.cpp(82) : error C2664: ''remove_if'' : cannot convert parameter 1 from ''struct isEqualToValue'' to ''class std::binder2nd<struct std::not_equal_to<class data> >''        No constructor could take the source type, or constructor overload resolution was ambiguous  


Why not have the functor body just be

return rhs.myValue == 3; 


Also as Sneftel said, just parameterize the constructor with the value you want to compare against. I think you''re confusing the syntax for constructing an object without a name and the ()-operator used in the functor. If you have a class named A, A() creates an unnamed instance of the object. If you have an instance of A named a, a() invokes the functor method body.
quote:Original post by Anonymous Poster
Why not have the functor body just be

return rhs.myValue == 3;  


Also as Sneftel said, just parameterize the constructor with the value you want to compare against. I think you''re confusing the syntax for constructing an object without a name and the ()-operator used in the functor. If you have a class named A, A() creates an unnamed instance of the object. If you have an instance of A named a, a() invokes the functor method body.


You''re right i keep forgetting you can do return (condition) and not just return (value)...

I''d like to get the above functor working before I parameterize it though.
you've called your class CData, yet you're parameterising your function with 'data'?

Here, watch. This compiles.


    include <list>#include <functional>using namespace std;struct MyClass {    int myValue;};struct isEqualToValue : public unary_function<MyClass, bool>{   bool operator() (MyClass &rhs) { return rhs.myValue == 3; }};int main(){        list<MyClass> L;        L.remove_if(isEqualToValue());        return 0;}  

I leave the runtime binding of the number as an exercise to the reader. (hint: it involves adding a member variable to isEqualToValue) How appropriate. You fight like a cow.

[edited by - sneftel on April 29, 2003 9:07:41 PM]
quote:Original post by Sneftel
you've called your class CData, yet you're parameterising your function with 'data'?

Here, watch. This compiles.


[edited by - sneftel on April 29, 2003 9:07:41 PM]



ok I created a new blank win32 console application project added a new .cpp and cut and paste the above code and lo and behold the same error message!


     --------------------Configuration: test - Win32 Debug--------------------Compiling...main.cppc:\program files\microsoft visual studio\vc98\my projects\tests\test\main.cpp(20) : error C2664: 'remove_if' : cannot convert parameter 1 from 'struct isEqualToValue' to 'class std::binder2nd<struct std::not_equal_to<struct MyClass> >'        No constructor could take the source type, or constructor overload resolution was ambiguousError executing cl.exe.test.exe - 1 error(s), 0 warning(s)     



Is there something silly I'm forgetting to do? It compiled fine on sneftel's machine so it must be something else...

edit: And I just called CData for the example above, the class was called data in the actual code.

edit2: weird tag behaviour..



[edited by - Kyo on April 29, 2003 9:22:55 PM]

[edited by - Kyo on April 29, 2003 9:24:07 PM]
What version of Visual C++ are you using? Could be a problem with their STL. You may want to consider getting STLPort.

How appropriate. You fight like a cow.
quote:Original post by Sneftel
What version of Visual C++ are you using? Could be a problem with their STL. You may want to consider getting STLPort.

How appropriate. You fight like a cow.


Oh yeah thought I mentioned it already i''m using VC++ 6.

Try changing unary_function<data, bool>
to unary_function<CData, bool>


This is a slightly more advanced approach:


  #include <boost\compose.hpp> #include <algorithm> #include <list> template<typename Class, class Alloc, class MemberType>void RemoveByMember(std::list<Class, Alloc>& list, MemberType Class::* mem_ptr, MemberType value)	{	list.remove_if(		boost::compose_f_gx(			std::bind1st(std::equal_to<MemberType>(), value),			MKH::STL::mem_accessor(mem_ptr)			)		);	} typedef std::list<CData> mylist_t;mylist_t list;RemoveByMember(list, &CData::value, 3);  


//mem_accessor

  namespace MKH	{	namespace STL		{ 		template<class Class, typename Result>		struct mem_accessor_t : std::unary_function<Class, Result>			{			typedef Result Class::* MemPtr;			mem_accessor_t(MemPtr mem_ptr) : mem_ptr(mem_ptr)				{}			MemPtr mem_ptr;			Result& operator()(Class& c) const				{				return c.*mem_ptr;				}			const Result& operator()(const Class& c) const				{				return c.*mem_ptr;				}			};		template<class Class, typename Result>		mem_accessor_t<Class, Result> mem_accessor(Result Class::* mem_ptr)			{			return mem_accessor_t<Class, Result>(mem_ptr);			} 		}	}[/soruce]  
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement