[fusion] Stateful unary functor for for_each loop
Hi there, is it possible to have a stateful functor object when using
fusion::for_each() loop.
I would like to to the following:
#include <vector>
#include
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code> for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway. Note that even if there were overloads for non-const references, the code as-ia wouldn't work because the function objects in the call to for_each are rvalues. Regards, Tobias
Thanks for the answer. I figured that from the error messages. So,
what would be the best to do? Singleton? Like this:
#include <vector>
#include
Christian Henning wrote:
Thanks for the answer. I figured that from the error messages. So, what would be the best to do?
Applying the attached changes should work.
Regards,
Tobias
--- fusion070319.cpp 2007-03-19 22:43:34.000000000 +0100
+++ fusion070319.cpp.orig 2007-03-19 22:42:07.000000000 +0100
@@ -1,7 +1,3 @@
-#include <iostream>
-#include <stdexcept>
-
-
#include <vector>
#include
Tobias Schwinger wrote:
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway.
IMO, this is a bug in Fusion. There should be an overload of for_each that takes a function object by non-const reference. Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up. -- Eric Niebler Boost Consulting www.boost-consulting.com
Eric Niebler wrote:
Tobias Schwinger wrote:
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway.
IMO, this is a bug in Fusion. There should be an overload of for_each that takes a function object by non-const reference. Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
Joel de Guzman wrote:
Eric Niebler wrote:
Tobias Schwinger wrote:
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway.
IMO, this is a bug in Fusion. There should be an overload of for_each that takes a function object by non-const reference.
For the function invokers I use by-value parameters and the templates are designed to allow explicitly specified template arguments to use references instead. The reason was that by-value arguments can be more efficient for small function objects (tracking side effects) and function pointers. It might be worthwhile to consider this scheme as an alternative to overloading, especially for algorithms which call back multiple times.
Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue.
No doubt here. Regards, Tobias
Tobias Schwinger wrote:
Joel de Guzman wrote:
Eric Niebler wrote:
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway. IMO, this is a bug in Fusion. There should be an overload of for_each
Tobias Schwinger wrote: that takes a function object by non-const reference.
For the function invokers I use by-value parameters and the templates are designed to allow explicitly specified template arguments to use references instead. The reason was that by-value arguments can be more efficient for small function objects (tracking side effects) and function pointers.
Really? Do you have some numbers to back that?
It might be worthwhile to consider this scheme as an alternative to overloading, especially for algorithms which call back multiple times.
Sure. Agreed; also, see below.
Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue.
No doubt here.
Ok, anyway, for the sake of discussion, the stl for_each is:
template
Joel de Guzman wrote:
Tobias Schwinger wrote:
Joel de Guzman wrote:
Eric Niebler wrote:
Christian Henning wrote:
Hi there, is it possible to have a stateful functor object when using fusion::for_each() loop.
I would like to to the following:
<snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway. IMO, this is a bug in Fusion. There should be an overload of for_each
Tobias Schwinger wrote: that takes a function object by non-const reference. For the function invokers I use by-value parameters and the templates are designed to allow explicitly specified template arguments to use references instead. The reason was that by-value arguments can be more efficient for small function objects (tracking side effects) and function pointers.
...and should've also mentioned STL here :-).
Really? Do you have some numbers to back that?
The effect in the first case (small or stateless function object by-value vs. by-reference) causes the compiler to omit certain optimizations if the scope becomes too wide, so numbers will greatly depend on the subject to optimization. I experienced a factor of ~50 for Fusion fuse/unfuse loopback (trying to apply factorizations to make the test code less ugly) with GCC, for instance. Of course there'll be a threshold somewhere for non-trivial copying... For the second case (pointer by-value vs. by-reference) there are some (possibly outdated) test results in the CallTraits documentation (you probably know that one).
It might be worthwhile to consider this scheme as an alternative to overloading, especially for algorithms which call back multiple times.
Sure. Agreed; also, see below.
Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue. No doubt here.
Ok, anyway, for the sake of discussion, the stl for_each is:
template
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); Ditto to all the other higher-order algos. What does that tell us?
Plus, if we design things to allow the template argument for the function to be specialized explicitly, we can have no-copy if we want to. We can also add a default argument for default constructible Function Objects. Regards, Tobias
Tobias Schwinger wrote:
Joel de Guzman wrote:
Tobias Schwinger wrote:
Joel de Guzman wrote:
Eric Niebler wrote:
Christian Henning wrote: > Hi there, is it possible to have a stateful functor object when using > fusion::for_each() loop. > > I would like to to the following: > <snip code>
for_each takes the function object by reference to const, so you have to const qualify operator() and make the data members mutable so you can change them anyway. IMO, this is a bug in Fusion. There should be an overload of for_each
Tobias Schwinger wrote: that takes a function object by non-const reference. For the function invokers I use by-value parameters and the templates are designed to allow explicitly specified template arguments to use references instead. The reason was that by-value arguments can be more efficient for small function objects (tracking side effects) and function pointers.
...and should've also mentioned STL here :-).
Really? Do you have some numbers to back that?
The effect in the first case (small or stateless function object by-value vs. by-reference) causes the compiler to omit certain optimizations if the scope becomes too wide, so numbers will greatly depend on the subject to optimization. I experienced a factor of ~50 for Fusion fuse/unfuse loopback (trying to apply factorizations to make the test code less ugly) with GCC, for instance. Of course there'll be a threshold somewhere for non-trivial copying...
For the second case (pointer by-value vs. by-reference) there are some (possibly outdated) test results in the CallTraits documentation (you probably know that one).
It might be worthwhile to consider this scheme as an alternative to overloading, especially for algorithms which call back multiple times. Sure. Agreed; also, see below.
Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue. No doubt here. Ok, anyway, for the sake of discussion, the stl for_each is:
template
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); Ditto to all the other higher-order algos. What does that tell us?
Plus, if we design things to allow the template argument for the function to be specialized explicitly, we can have no-copy if we want to. We can also add a default argument for default constructible Function Objects.
Looks like Tobias is offering a superior design. What do you think, Eric? Tobias, we'd still need some perf tests to back this up. CallTraits is quite old and the tests there (if there are) might not be relevant anymore. For example, in the fusion fold tests, I see that VC7.1 produces highly optimal code. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
Joel de Guzman wrote:
Tobias Schwinger wrote:
Joel de Guzman wrote:
Tobias Schwinger wrote:
Joel de Guzman wrote:
Eric Niebler wrote:
Tobias Schwinger wrote: > Christian Henning wrote: >> Hi there, is it possible to have a stateful functor object when using >> fusion::for_each() loop. >> >> I would like to to the following: >> > <snip code> > > for_each takes the function object by reference to const, so you have to > const qualify operator() and make the data members mutable so you can > change them anyway. IMO, this is a bug in Fusion. There should be an overload of for_each that takes a function object by non-const reference. For the function invokers I use by-value parameters and the templates are designed to allow explicitly specified template arguments to use references instead. The reason was that by-value arguments can be more efficient for small function objects (tracking side effects) and function pointers. ...and should've also mentioned STL here :-).
Really? Do you have some numbers to back that? The effect in the first case (small or stateless function object by-value vs. by-reference) causes the compiler to omit certain optimizations if the scope becomes too wide, so numbers will greatly depend on the subject to optimization. I experienced a factor of ~50 for Fusion fuse/unfuse loopback (trying to apply factorizations to make the test code less ugly) with GCC, for instance. Of course there'll be a threshold somewhere for non-trivial copying...
For the second case (pointer by-value vs. by-reference) there are some (possibly outdated) test results in the CallTraits documentation (you probably know that one).
It might be worthwhile to consider this scheme as an alternative to overloading, especially for algorithms which call back multiple times. Sure. Agreed; also, see below.
Stateful predicates should be supported, and Fusion should be explicit about where and when predicates are copied, so that the state doesn't get messed up.
I agree. This is one of the todo items. Noted and added in the queue. No doubt here. Ok, anyway, for the sake of discussion, the stl for_each is:
template
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); Ditto to all the other higher-order algos. What does that tell us? Plus, if we design things to allow the template argument for the function to be specialized explicitly, we can have no-copy if we want to. We can also add a default argument for default constructible Function Objects.
Looks like Tobias is offering a superior design. What do you think, Eric?
Tobias, we'd still need some perf tests to back this up. CallTraits is quite old and the tests there (if there are) might not be relevant anymore. For example, in the fusion fold tests, I see that VC7.1 produces highly optimal code.
Frankly, I think the proposed design (function object passed by value, or by reference with explicitly specified template arg) is ugly. It'll be ugly both from the user's perspective and in the implementation. If by-value is a perf-win in the common case (perf numbers?), then I'd prefer by-ref semantics to look like this: for_each( seq, ref(func) ); instead of this: for_each< Func & >( seq, func ); -- Eric Niebler Boost Consulting www.boost-consulting.com
on Wed Mar 21 2007, Eric Niebler
Frankly, I think the proposed design (function object passed by value, or by reference with explicitly specified template arg) is ugly. It'll be ugly both from the user's perspective and in the implementation. If by-value is a perf-win in the common case (perf numbers?), then I'd prefer by-ref semantics to look like this:
for_each( seq, ref(func) );
instead of this:
for_each< Func & >( seq, func );
Good call. But please, everyone, let's avoid over-quoting. -- Dave Abrahams Boost Consulting www.boost-consulting.com
Eric Niebler wrote:
Frankly, I think the proposed design (function object passed by value, or by reference with explicitly specified template arg) is ugly. It'll be ugly both from the user's perspective and in the implementation.
OK, but why? For the fusion/functional module the implementation part turned to be rather smooth. I must admit that for algorithms (where the function isn't the first parameter) the different ordering of the template parameters slightly bugs me.
If by-value is a perf-win in the common case (perf numbers?),
I don't think it is. There are cases where it gets optimized better, however. You can observe the effect by s/F const &/F/g in libs/fusion/example/performance/functional.cpp using GCC, bjam release-mode options. Note there is only a small (but clearly measurable) difference in this case (it's not the one I've been talking about in my previous post -- too much work to reconstruct now, sorry). But, as said, numbers don't say much, since they entirely depend on the code that is to be optimized.
then I'd prefer by-ref semantics to look like this:
for_each( seq, ref(func) );
If ef wrap/unwrap optimizes out entirely, this variant looks like a nice alternative. Another one would be to forget about the whole thing. There is a 'mutable' keyword, after all -- and, alternatively, a Function Object may reference an external state. Regards, Tobias
Tobias Schwinger wrote:
Eric Niebler wrote:
Frankly, I think the proposed design (function object passed by value, or by reference with explicitly specified template arg) is ugly. It'll be ugly both from the user's perspective and in the implementation.
OK, but why?
Because it forces users to repeat the type of the function object. Isn't it nicer to say for_each( seq, ref(func) ) instead of for_each< Func &
( seq, func )?
-- Eric Niebler Boost Consulting www.boost-consulting.com
participants (5)
-
Christian Henning
-
David Abrahams
-
Eric Niebler
-
Joel de Guzman
-
Tobias Schwinger