Question: How to refer to object members in predicates 
Author Message
 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  
 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  
 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  
 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 non-std 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

- Show quoted text -

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  
 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/cs-win32.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  
 
 [ 5 post ] 

 Relevant Pages 

1. vc6: View method to refer to App class member variable

2. Referring to structure member inside structure

3. Need help on Predicate objects, binding...

4. newbie - how to refer an object within the dialog box

5. pointer that refer to automatic object...

6. sort predicate question

7. Question about initializing member objects

8. Newbie question: What is wrong with my predicate?

9. Object member objects

10. Passing a Pointer of an Object to its member Object

11. question about copying 16-or-256 GDI bitmap object to monochrome bitmap object by bitblt

12. An object as a static class member

 

 
Powered by phpBB® Forum Software