 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Dhruv Guest
|
Posted: Fri Jan 23, 2004 10:11 am Post subject: Passing Functors to STL algorithms by Reference. |
|
|
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
|
Posted: Sat Jan 24, 2004 1:22 pm Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
"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
|
Posted: Sun Jan 25, 2004 10:42 am Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
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
|
Posted: Sun Jan 25, 2004 5:31 pm Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
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
|
Posted: Mon Jan 26, 2004 12:07 am Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
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
|
Posted: Mon Jan 26, 2004 8:33 pm Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
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
|
Posted: Wed Jan 28, 2004 10:08 am Post subject: Re: Passing Functors to STL algorithms by Reference. |
|
|
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 |
|
 |
|
|
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
|
|