Tobias Schwinger wrote:
Then 'switch_<void>(n)' is a fused function and 'cases' a sequence of cases (whether implemented with Fusion or not)...
The number of cases *can* vary at compile time. I have a guess that we're talking past each other.
Yes, obviously -- I think because of a pair of parentheses. This code
switch_<result>(n) (( // ... hand-written cases, note (( )) ));
would've told me more easily what you're up to :-).
I often add the double parens. Someone asked why at BoostCon'07. I answered "because I like it" :-) Now, I have a more valid reason. Yeah... sorry about the confusion.
For the purpose of clarification, let me call the original interface A and my proposal B.
Again:
* Transforming A to B requires minimal amount of coding. The smarts is already in the PP code. The cost is cheap. The cost is cheap and the effect is destructive :-).
Why is it destructive?
We lose the index and the chance to easily use a single function for all cases.
Index: * I also recall sometime ago when attributes for Spirit2 was being discussed. For alternates: (a | b | c)[f] the question was: do f receive the index or not. Many times it is useful. * With for_each (and many of the algorithms), one disadvantage over the lowly for or while is the access to the index of the iterator. Many times those are usefule too. My answer to these kind of concerns now is: bind it when you need it. Single function: I'm a strong advocate of smaller is better. Modularity matters. Big classes (or in this case function objects), metaprogram blobs (i.e. traits), humongous enums, and all such sort of dinosours :-) are best avoided. They are convenient up to a certain extent and becomes unmanageable beyond a certain limit. In all of my use cases, I have N functions that are provided elsewhere and I have no control over (e.g. parser functions). I insist that this is the more common use case. Grouping them into a single big struct is an unnecessary and cumbersome step. Still, if people insist, I outlined a way to convert the big function object to smaller 'bound' objects, in another post. Just bind 'em into smaller function chunks.
You must be seeing a use-case that I don't.
Yes, see below.
[...]
To be honest, I really don't see your point. I still don't see why you'd want to build A on top of B.
1. As a thought experiment to figure out which of the two variants is the more basic one, and
2. for parameterizing a single function with compile time information looked up by index (it's quite common and -as you can probably guess- the index can be very handy inside the metaprogram).
Now that I have figured out that your interface accepts sequences, we can actually express the transforms between the two:
A ---> B: function := L(I): functions[I]() B ---> A: transform(cases, L(I): make_pair<I>(bind(function,I())))
// Notation: // ========= // uppercase - types // lowercase - objects // L(args): - lambda composition
I don't expect us to a reach consensus, but hopefully we do understand each other's points now.
That's a relief ;-) Now that that's cleared, let me /push/ now the other benefits of my proposed interface: * Ability to allow fall-through and break: case_<1>(f1, break_), // no fall-through case_<2>(f2), // fall-through (by default) * Allow multiple case handling: case_<'x', 'y'>(f2), // handle 'x' and 'y' Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net