how to use find_if and other functors ?

Started by
6 comments, last by Fruny 18 years, 4 months ago

#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!
Advertisement
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,
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!! :)
Is there any comments?
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;};
I mean that whether I can use existing STL functors, algoriths..etc to realize this functionality without write my own functor.

Keep it up!
You could provide an operator == for your type, and then use a combination of std::bind2nd and std::equals<type>
daerid@gmail.com
Quote:Original post by KevinLee
I mean that whether I can use existing STL functors, algoriths..etc to realize this functionality without write my own functor.


That's the purpose behind boost::bind, boost::mem_fn, boost::lambda, Phoenix and a number of other similar libraries.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement