Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Kyo

STL remove_if

This topic is 5531 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 )

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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


Share this post


Link to post
Share on other sites
Guest 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.cpp
c:\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 ambiguous
Error 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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!