Question: How to refer to object members in predicates
Author 
Message 
Ladvánszky Károl #1 / 5

Question: How to refer to object members in predicates
I'd like to construct predicates from STL functors (i.e. without writing my own functor). For collections of scalars this is easy. vector<int> vi ; int cnt = count_if (va.begin(), va.end() , bind2nd(greater<int>(),4)) ; Is there any way to do the same in the case of object collections? class Alfa { public : int m_x ; } ; vector<Alfa> va ; int cnt = count_if (va.begin(), va.end(), xxx ) ; // xxx ? Please help. Kroly Ladvnszky

Sat, 25 Dec 2004 22:09:59 GMT 


Ken Alverso #2 / 5

Question: How to refer to object members in predicates
<snip> Quote: > int cnt = count_if (va.begin(), va.end() , bind2nd(greater<int>(),4)) ; > Is there any way to do the same in the case of object collections? > class Alfa { public : int m_x ; } ; > vector<Alfa> va ; > int cnt = count_if (va.begin(), va.end(), xxx ) ; // xxx ?
Yes and no. First of all, you need an accessor function, you can't go off of a field like that. That simply means something like: class Alfa { int m_x; public: int getx() const {return m_x;} Quote: };
which is a good idea anyway, it gives you more leeway if you later decide to change m_x. Second of all, you need a functor composer  a functor that takes two or more functions and composes them (uses the result of one as the input of the other). SGI's STL has this as an extension, I believe boost has something like this, or you can use the one I wrote, which is: template<typename Fn1, typename Fn2> struct unary_compose : unary_function<typename Fn2::argument_type,typename Fn1::result_type> { unary_compose(const Fn1& f1,const Fn2& f2):f1(f1),f2(f2) {} result_type operator()(const argument_type& arg) { return f1(f2(arg)); } private: Fn1 f1; Fn2 f2; Quote: };
template <typename Fn1, typename Fn2> unary_compose<Fn1, Fn2> compose1(const Fn1& f1, const Fn2& f2) { return unary_compose<Fn1,Fn2>(f1,f2); Quote: }
Once you have that, you can finally build your functor. It should look like this: int cnt = (int)count_if (va.begin(), va.end(), compose1( bind2nd(greater<int>(),4), mem_fun_ref(Alfa::getx) ) ); This says that for each Alfa object in your vector, getx will be called, and the result of that will be fed into the greater function, which has its second parameter bound to four. Ken

Sun, 26 Dec 2004 02:38:12 GMT 


Ladvánszky Károl #3 / 5

Question: How to refer to object members in predicates
Thanks Ken for your answer, it has been very useful for me indeed. As for the Boost library, I would very much like to use it but it does not compile with VC. Do you know of an easy solution to get it working? Cheers, Kroly
Quote:
> <snip> > > int cnt = count_if (va.begin(), va.end() , bind2nd(greater<int>(),4)) ; > > Is there any way to do the same in the case of object collections? > > class Alfa { public : int m_x ; } ; > > vector<Alfa> va ; > > int cnt = count_if (va.begin(), va.end(), xxx ) ; // xxx ? > Yes and no. First of all, you need an accessor function, you can't go off > of a field like that. That simply means something like: > class Alfa { > int m_x; > public: > int getx() const {return m_x;} > }; > which is a good idea anyway, it gives you more leeway if you later decide to > change m_x. Second of all, you need a functor composer  a functor that > takes two or more functions and composes them (uses the result of one as the > input of the other). SGI's STL has this as an extension, I believe boost > has something like this, or you can use the one I wrote, which is: > template<typename Fn1, typename Fn2> > struct unary_compose : unary_function<typename Fn2::argument_type,typename > Fn1::result_type> { > unary_compose(const Fn1& f1,const Fn2& f2):f1(f1),f2(f2) {} > result_type operator()(const argument_type& arg) { > return f1(f2(arg)); > } > private: > Fn1 f1; > Fn2 f2; > }; > template <typename Fn1, typename Fn2> > unary_compose<Fn1, Fn2> compose1(const Fn1& f1, const Fn2& f2) { > return unary_compose<Fn1,Fn2>(f1,f2); > } > Once you have that, you can finally build your functor. It should look like > this: > int cnt = (int)count_if (va.begin(), va.end(), > compose1( > bind2nd(greater<int>(),4), > mem_fun_ref(Alfa::getx) > ) > ); > This says that for each Alfa object in your vector, getx will be called, and > the result of that will be fed into the greater function, which has its > second parameter bound to four. > Ken

Sun, 26 Dec 2004 15:14:47 GMT 


Boris Vidolo #4 / 5

Question: How to refer to object members in predicates
Hi, Note that for objects you can define operator '>': class Alfa { public : int m_x ; } ; bool operator > (const Alfa& ra, int n) { return ra.m_x > n; } Then, you would expect that your declaration: int cnt = count_if (va.begin(), va.end() , bind2nd(greater<Alpha, int>(),4)) ; would do, but it doesn't as the creators of STL never thought of the fact that "operator >" can have different arguments ("Alfa" and "int" in our case), so you just write you own "greater", with a little change to the STL's one: template<class _Tx, class _Ty> struct greater : binary_function<_Tx, _Ty, bool> { bool operator()(const _Tx& _X, const _Ty& _Y) const {return (_X > _Y); } Quote: };
So your nonstd greater has two template arguments and now uou can use it in the upper way. Regards, Boris
Quote: > Thanks Ken for your answer, it has been very useful for me indeed. > As for the Boost library, I would very much like to use it but it does not > compile with VC. > Do you know of an easy solution to get it working? > Cheers, > Kroly
> > <snip> > > > int cnt = count_if (va.begin(), va.end() , bind2nd(greater<int>(),4)) ; > > > Is there any way to do the same in the case of object collections? > > > class Alfa { public : int m_x ; } ; > > > vector<Alfa> va ; > > > int cnt = count_if (va.begin(), va.end(), xxx ) ; // xxx ? > > Yes and no. First of all, you need an accessor function, you can't go off > > of a field like that. That simply means something like: > > class Alfa { > > int m_x; > > public: > > int getx() const {return m_x;} > > }; > > which is a good idea anyway, it gives you more leeway if you later decide > to > > change m_x. Second of all, you need a functor composer  a functor that > > takes two or more functions and composes them (uses the result of one as > the > > input of the other). SGI's STL has this as an extension, I believe boost > > has something like this, or you can use the one I wrote, which is: > > template<typename Fn1, typename Fn2> > > struct unary_compose : unary_function<typename
Fn2::argument_type,typename Quote: > > Fn1::result_type> { > > unary_compose(const Fn1& f1,const Fn2& f2):f1(f1),f2(f2) {} > > result_type operator()(const argument_type& arg) { > > return f1(f2(arg)); > > } > > private: > > Fn1 f1; > > Fn2 f2; > > }; > > template <typename Fn1, typename Fn2> > > unary_compose<Fn1, Fn2> compose1(const Fn1& f1, const Fn2& f2) { > > return unary_compose<Fn1,Fn2>(f1,f2); > > } > > Once you have that, you can finally build your functor. It should look > like > > this: > > int cnt = (int)count_if (va.begin(), va.end(), > > compose1( > > bind2nd(greater<int>(),4), > > mem_fun_ref(Alfa::getx) > > ) > > ); > > This says that for each Alfa object in your vector, getx will be called, > and > > the result of that will be fed into the greater function, which has its > > second parameter bound to four. > > Ken

Sun, 26 Dec 2004 15:50:14 GMT 


Ken Alverso #5 / 5

Question: How to refer to object members in predicates
Quote: > Thanks Ken for your answer, it has been very useful for me indeed. > As for the Boost library, I would very much like to use it but it does not > compile with VC. > Do you know of an easy solution to get it working?
I haven't installed boost lately, but I think that the boost "bind" library will do what you want, and according to this chart bind works on VC (at least vc6): http://www.boost.org/status/cswin32.html They don't indicate whether or not bind will work on vc7, but they do have build instructions for vc7, so I'd bet it does. Build instructions are here: http://www.boost.org/tools/build/index.html Boost's bind handles the functionality of bind1st, bind2nd, compose1, compose2, and more  usage details are here: http://www.boost.org/libs/bind/bind.html Ken

Sun, 26 Dec 2004 16:15:31 GMT 


