struct isEqualToValue : public unary_function<data, bool>
{
bool operator() (data &rhs) { if (rhs.myValue == 3) { return true; } else { return false; } }
};
L.remove_if(isEqualToValue());
STL remove_if
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:
Thanks for reading through (and hopefully enlightening me with a reply )
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.
How appropriate. You fight like a cow.
It''s possible to do list.remove(isEqualToValue(3))?
The error is:
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
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.
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 bereturn 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.
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]
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.
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:
//mem_accessor
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]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement