C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Passing Functors to STL algorithms by Reference.

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Dhruv
Guest





PostPosted: Fri Jan 23, 2004 10:11 am    Post subject: Passing Functors to STL algorithms by Reference. Reply with quote



I have here a helper class that allows me to pass functors by reference to
STL functions such as find, for_each, etc...


//Used to pass a Functor to functions by reference.
template <typename Functor>
class Functor_Ref {
Functor& FRef;

public:
Functor_Ref (Functor& _fref) : FRef(_fref) { }
//operator Functor& () { return FRef; }
template <typename X>
bool operator() (X _x) { return FRef (_x); }
};


If anyone has a better solution than this one, please let me know. Are
there any defects in the helper class that I'm currently using?

Also, I'd like to know why doesn't the thing work when I just uncomment
the operator Functor& (), and comment out the forwarding function
operator()?


Regards,
-Dhruv.




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Michael Tiomkin
Guest





PostPosted: Sat Jan 24, 2004 1:22 pm    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote



"Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote

Quote:
I have here a helper class that allows me to pass functors by reference to
STL functions such as find, for_each, etc...


//Used to pass a Functor to functions by reference.
template class Functor_Ref {
Functor& FRef;

public:
Functor_Ref (Functor& _fref) : FRef(_fref) { }
//operator Functor& () { return FRef; }
template bool operator() (X _x) { return FRef (_x); }
};


If anyone has a better solution than this one, please let me know. Are
there any defects in the helper class that I'm currently using?

Yes, you can pass the Functor itself, instead of the helper.

Quote:
Also, I'd like to know why doesn't the thing work when I just uncomment
the operator Functor& (), and comment out the forwarding function
operator()?

The () operator in this case doesn't take an argument and returns
a type that isn't exactly boolean (Functor&). You can uncomment
both of them and use both operators in different cases. Notice that
foreach needs the second operator, "(X x)".

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Sun Jan 25, 2004 10:42 am    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote



On 23 Jan 2004 05:11:09 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

Quote:
I have here a helper class that allows me to pass functors by reference to
STL functions such as find, for_each, etc...

//Used to pass a Functor to functions by reference.
template <typename Functor
class Functor_Ref {
Functor& FRef;
public:
Functor_Ref (Functor& _fref) : FRef(_fref) { }
//operator Functor& () { return FRef; }
template bool operator() (X _x) { return FRef (_x); }
};

Are there any defects in the helper class that I'm currently using?

Functors sent to for_each do not usually return anything from operator()
because it is ignored by for_each. You require a bool return. Since
you are only using functors and never functions, you can demand that
it be derived from unary_function. That gives a nice function.

typename Functor::result_type
operator() (typename Functor::argument_type x) { return FRef(x); }

Quote:
If anyone has a better solution than this one, please let me know.

Only a value judgement on the utility.

struct Sum : public unary_function int sum;
Sum () : sum(0) { }
void operator() (int x) { sum += x; }
};
void f (Sum& sum) {
vector<int> v(5, 1);
for_each(v.begin(), v.end(), Functor_Ref<Sum>(sum));
for_each<vector(v.begin(), v.end(), sum);
sum = for_each(v.begin(), v.end(), sum);
}

I think that I prefer the third. I don't follow the need for using
a predicate by reference. Assuming that you do have a need, you should
also note that the standard prohibits predicates with side effects.
Ignoring that, your Functor_Ref should work with find_if while the other
two methods are not likely to work.

Another approach is to make the data member static or a reference to be
initialized in the constructor. Just one more way to fight the value
semantics of the STL.

Quote:
Also, I'd like to know why doesn't the thing work when I just uncomment
the operator Functor& (), and comment out the forwarding function
operator()?

Inside of some algorithm we have, func(*first). You want it to
implicitely become ((Functor&)func)(*first). I think that is
asking a bit too much. Implicit conversions on the arguments to
a function, but not on the function itself. In this case, we have
a function object and you are asking for an implicit conversion on
the implicit this argument.

func(*first) == func.operator()(*first) !=
(func.operator Functor&()).operator()(*first)


John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Frank Birbacher
Guest





PostPosted: Sun Jan 25, 2004 5:31 pm    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote

Hi!

Dhruv wrote:
Quote:
Also, I'd like to know why doesn't the thing work when I just uncomment
the operator Functor& (), and comment out the forwarding function
operator()?

Because the function call operator does not make type conversions
necessary for the object being called on.

Frank


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dhruv
Guest





PostPosted: Mon Jan 26, 2004 12:07 am    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote

On Sun, 25 Jan 2004 05:42:58 -0500, John Potter wrote:

Quote:
On 23 Jan 2004 05:11:09 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

I have here a helper class that allows me to pass functors by reference to
STL functions such as find, for_each, etc...

//Used to pass a Functor to functions by reference.
template <typename Functor
class Functor_Ref {
Functor& FRef;
public:
Functor_Ref (Functor& _fref) : FRef(_fref) { }
//operator Functor& () { return FRef; }
template bool operator() (X _x) { return FRef (_x); }
};

Are there any defects in the helper class that I'm currently using?

Functors sent to for_each do not usually return anything from operator()
because it is ignored by for_each. You require a bool return. Since
you are only using functors and never functions, you can demand that
it be derived from unary_function. That gives a nice function.

Is it mandated that the functors passed to the standard algorithm be
derived from unary_function? Or is it required that they have these
nested typedefs, or neither condition is required?

Quote:
typename Functor::result_type
operator() (typename Functor::argument_type x) { return FRef(x); }


Thanks for pointing out this possible scaleability feature to me!

Quote:
If anyone has a better solution than this one, please let me know.

Only a value judgement on the utility.

struct Sum : public unary_function int sum;
Sum () : sum(0) { }
void operator() (int x) { sum += x; }
};
void f (Sum& sum) {
vector<int> v(5, 1);
for_each(v.begin(), v.end(), Functor_Ref<Sum>(sum));
for_each<vector(v.begin(), v.end(), sum);
sum = for_each(v.begin(), v.end(), sum);
}

I think that I prefer the third. I don't follow the need for using
a predicate by reference. Assuming that you do have a need, you should
also note that the standard prohibits predicates with side effects.
Ignoring that, your Functor_Ref should work with find_if while the other
two methods are not likely to work.

What do mean by 'Functors with Side Effects'?

Quote:
Another approach is to make the data member static or a reference to be
initialized in the constructor. Just one more way to fight the value
semantics of the STL.

I can't do that since the application and hence the functor may be used in
a Multi-Threaded Environment.

However, it's a nice useful solution!

Quote:
Also, I'd like to know why doesn't the thing work when I just uncomment
the operator Functor& (), and comment out the forwarding function
operator()?

Inside of some algorithm we have, func(*first). You want it to
implicitely become ((Functor&)func)(*first). I think that is
asking a bit too much. Implicit conversions on the arguments to
a function, but not on the function itself. In this case, we have
a function object and you are asking for an implicit conversion on
the implicit this argument.

func(*first) == func.operator()(*first) !=
(func.operator Functor&()).operator()(*first)

I was expecting something like this to happen! I used the same logic used
for the implicit copy ctor call when used as such:

struct A { };

A a;
A b = a; //Implicit call to copy ctor. 1 UDC allowed.

Similarly, I thought that the 1 UDC of calling the operator Functor&()
would work, but as you said, it doesn't! So much for that idea!!!


Regards,
-Dhruv.




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Mon Jan 26, 2004 8:33 pm    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote

On 25 Jan 2004 19:07:23 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

Quote:
Is it mandated that the functors passed to the standard algorithm be
derived from unary_function? Or is it required that they have these
nested typedefs, or neither condition is required?

The standard algorithms are designed to work with plain pointer to
function. The typedefs are for other things like function adaptors.
Since your functor is meaningless for a pointer to function you can
consider it an adaptor and demand the typedefs.

Quote:
What do mean by 'Functors with Side Effects'?

Pure functions return results without changing parameters or globals.
Any change is a side effect. The functor with state that you are
wrapping violates the no side effects rule.

Quote:
Another approach is to make the data member static or a reference to be
initialized in the constructor. Just one more way to fight the value
semantics of the STL.

I can't do that since the application and hence the functor may be used in
a Multi-Threaded Environment.

Then you can't use a static, but a reference is still usable.

struct Sum {
int& sum;
Sum (int& sum) : sum(sum) { }
void operator() (int x) { sum += x; }
};
int f (vector<int> const& v) {
int total;
for_each(v.begin(), v.end(), Sum(total));
return total;
}

It still violates no side effects, but rules were made to be broken.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Wed Jan 28, 2004 10:08 am    Post subject: Re: Passing Functors to STL algorithms by Reference. Reply with quote

John Potter <jpotter (AT) falcon (DOT) lhup.edu> wrote

Quote:
On 25 Jan 2004 19:07:23 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

I can't do that since the application and hence the functor may be
used in a Multi-Threaded Environment.

Then you can't use a static, but a reference is still usable.

struct Sum {
int& sum;
Sum (int& sum) : sum(sum) { }
void operator() (int x) { sum += x; }
};
int f (vector<int> const& v) {
int total;
for_each(v.begin(), v.end(), Sum(total));
return total;
}

It still violates no side effects, but rules were made to be broken.

Are you sure? The standard doesn't say much about functional
objects -- I can't find the requirement that they have to be copy
constructable, for example. And it wouldn't surprise me if there
wasn't a requirement somewhere that they be assignable; the principle
of least surprise dictates that objects which have value semantics are
both copy constructable and assignable, and that objects which don't
have value semantics are neither. (I often use similar functional
objects, but with a pointer in the class. So that they are implicitly
assignable.)

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.