[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

std::find_if in vector

eiji.anonremail

11/5/2008 10:09:00 AM

I would like to search in a vector depending on "a" or "a and b"
without the overhead of creating a Foo object or another predicate
class.

Is that possible? Using a member function pointer or a global static
function?
Right now I have this, but I don't like it.

------------------------------Example
code----------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

class Foo {

public:
Foo(int aa, int bb, int cc):a(aa),b(bb),c(cc) {}

bool operator()(const Foo& f) {
return (GetA() == f.GetA() &&
GetB() == f.GetB() &&
GetC() == f.GetC());
}

inline int GetA() const {return a;}
inline int GetB() const {return b;}
inline int GetC() const {return c;}

private:
int a,b,c;
};

class Foo_eq_a : public std::unary_function<Foo, bool> {
public:
explicit Foo_eq_a(int aa):a(aa) {}

bool operator() (const Foo& f) const
{
return (f.GetA() == a);
}
private:
int a;
};
class Foo_eq_ab : public std::unary_function<Foo, bool> {
public:
explicit Foo_eq_ab(int aa, int bb):eq_a(aa),b(bb) {}

bool operator() (const Foo& f) const
{
return (eq_a(f) && f.GetB() == b);
}
private:
Foo_eq_a eq_a;
int b;
};

int main()
{
std::vector<Foo> foos;

foos.push_back(Foo(1,1,1));
foos.push_back(Foo(1,2,2));
foos.push_back(Foo(1,2,3));


std::vector<Foo>::const_iterator citer;
citer = std::find_if(foos.begin(), foos.end(), Foo(1,2,3));
if (citer != foos.end())
std::cout << "operator() hit, okay" << std::endl;

citer = std::find_if(foos.begin(), foos.end(), Foo(1,2,4));
if (citer == foos.end())
std::cout << "operator() no hit, okay" << std::endl;


citer = std::find_if(foos.begin(), foos.end(), Foo_eq_ab(1,2));
if (citer == ++foos.begin())
std::cout << "position 1, okay" << std::endl;

system("Pause");
}

----------------------------------
Any suggestions?
Thanks
5 Answers

Sam

11/5/2008 12:01:00 PM

0

eiji.anonremail@googlemail.com writes:

> I would like to search in a vector depending on "a" or "a and b"
> without the overhead of creating a Foo object or another predicate
> class.
>
> Is that possible? Using a member function pointer or a global static
> function?

Use std::ptr_fun to turn your global static function into a suitable
function object.

Eric.Malenfant@gmail.com

11/5/2008 2:21:00 PM

0

eiji.anonrem...@googlemail.com a écrit :
> I would like to search in a vector depending on "a" or "a and b"
> without the overhead of creating a Foo object or another predicate
> class.

Maybe a lambda?

With:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
namespace bl = boost::lambda;

This:
std::find_if(f.begin(), f.end(), (bl::bind(&Foo::GetA, bl::_1) == 1)
&& (bl::bind(&Foo::GetB, bl::_1) == 2));
could replace:
std::find_if(foos.begin(), foos.end(), Foo_eq_ab(1,2));

eiji.anonremail

11/5/2008 3:55:00 PM

0



> Use std::ptr_fun to turn your global static function into a suitable
> function object.

This is not possible, since you can not pass in arguments, from what I
know.

To turn this:
citer = std::find_if(foos.begin(), foos.end(), Foo_eq_ab(1,2));

into
class Foo {
....
public:
static bool eq_ab(const Foo& f) {return false}
....
};

There is no possibility to pass "1,2".

??

eiji.anonremail

11/5/2008 4:01:00 PM

0

> Maybe a lambda?
>
> With:
> #include <boost/lambda/lambda.hpp>
> #include <boost/lambda/bind.hpp>
> namespace bl = boost::lambda;
>
> This:
> std::find_if(f.begin(), f.end(), (bl::bind(&Foo::GetA, bl::_1) == 1)
> && (bl::bind(&Foo::GetB, bl::_1) == 2));
> could replace:
> std::find_if(foos.begin(), foos.end(), Foo_eq_ab(1,2));

Two reasons why not:
- boost is not an option :-/
- I wan't to encapsulate (x == y && z == y ...) in one place. Using
this approach, I would again have to change lot's of places when
search pattern changes a bit. The search pattern and the call should
be clean seperated as far as possible.

Sam

11/5/2008 11:23:00 PM

0

eiji.anonremail@googlemail.com writes:

>
>
>> Use std::ptr_fun to turn your global static function into a suitable
>> function object.
>
> This is not possible, since you can not pass in arguments, from what I
> know.
>
> To turn this:
> citer = std::find_if(foos.begin(), foos.end(), Foo_eq_ab(1,2));
>
> into
> class Foo {
> ...
> public:
> static bool eq_ab(const Foo& f) {return false}
> ...
> };
>
> There is no possibility to pass "1,2".

static bool Foo_eq_b(int n)
{
return Foo_eq_a_b(1, 2, n);
}

std::find_if(foos.begin(), foos.end(), std::ptr_fun(Foo_eq_b));

… or whatever.