Sign in to follow this  
KevinLee

how to use find_if and other functors ?

Recommended Posts

#include <map>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

typedef struct _tagKeyType
{
	int iKey;
	double dKey;
}KeyType, *PKeyType;


typedef struct _tagValueType
{
	int iValue;
	double dValue;
}ValueType, *PValueType;

int _tmain(int argc, _TCHAR* argv[])
{
	map<KeyType*, ValueType> Foo;
	
	KeyType key={0, 0.0};
	ValueType value={0, 0.0};

        //Insert some node to this map,
        //I just insert some stack object here to demostrate it
	Foo[&key] = value;
        Foo[...] = ...
       
        //? How to write it here?
        map<KeyType*, ValueType>::Iterator iter = find_if(.....)

	return 0;
}

Presently, I write this example, I want to know,how to complete this find_if function using stl algorithm. The code maybe like this:
for(iter = begin; iter !=end; iter ++)
{
   if(iter->second.iKey == somevalue)
         return iter;
}

E.g., I want to find_if use the iKey value as the conditions and I also want to use the most helpful of STL but not my own method to find it. Thanks!

Share this post


Link to post
Share on other sites
Hello,

First, find_if() is not a functor. A functor is an object that act like a function. To be able to do so, it has to override the operator(), like in this example:

struct MyComparisonFunctor
{
bool operator()(int param1, int param2)
{
return param1 < param2;
}
};

Calling this code is trivial:

MyComparisonFunctor functor;
if (functor(1, 2)) {
std::cout << "1 < 2!!!!11 Incredebal!!!11" << std::endl;
}


std::find_if uses a predicate to perform the comparison. A predicate is either a functor or a function pointer. A correct way to use find_if is to define a function like this:

std::vector<int> v;
bool find_my_key(int k)
{
if (k == 32) return true;
return false;
}
// use find_if:
std::vector<int>::iterator iter = std::find_if(v.begin(), v.end(), find_my_key);

Another way is to define a functor. In this case, it is considered a good practice to inherit this functor from either std::unary_function or std::binary_function (depending on your needs, of course):

#include <functional>

struct FindKey : public std::unary_function<int, bool>
{
FinKey(const argument_type& key_to_find) : mKeyToFind(key_to_find) { }
result_type operator() (const argument_type& value)
{
return (result_type) (value == mKeyToFind);
}
private:
argument_type mKeyToFind;
}

// use find_if:
FindKey finder(32);
std::vector<int>::iterator iter = std::find_if(v.begin(), v.end(), finder);


I'd like to add one more thing: if you want to find if an object exists in the map I suggest you to use map<>::find() instead of std::find_if(). The former might be optimized to find your key faster, while the later will force you to run a O(n) algorithm. Of course, your search need might be different (and maybe a map is not the correct container to use then).

HTH,

Share this post


Link to post
Share on other sites
Hi, Emmanuel Deloget,

Thanks for you fast reply. However, I know how to use find_if with some simple functor or function, but it seams that in this program, it could be a little difficult, as you can see, I want to compare the iter->second.iKey.

I know your suggestion, and I think it do works. But, I wonder if there is anyone who can write a more neat code here, just using stl functors, such as bind2end, mem_fun...etc, so that I need not to define my own functor or functions.

I don't know whether I have express myself clearly.
Any way, thanks for your kind reply!! :)

Share this post


Link to post
Share on other sites
Making it work with find_if in your example is just as simple:


struct MyUnaryFunctor
{
MyUnaryFunctor(int i) : m_i(i) { }
bool operator()(const std::pair<KeyType*,ValueType> &m1)
{
return param1.second.iKey == m_i;
}

int m_i;
};

Share this post


Link to post
Share on other sites
I mean that whether I can use existing STL functors, algoriths..etc to realize this functionality without write my own functor.

Keep it up!

Share this post


Link to post
Share on other sites
You could provide an operator == for your type, and then use a combination of std::bind2nd and std::equals<type>

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this