
Tobias Schwinger wrote:
Joel de Guzman wrote:
Tobias Schwinger wrote:
Tobias Schwinger wrote:
I'm still playing with it and hope I can add some details here, soon.
I wanted to use Fusion to write something (well, at least half-way) real for review, so I chose to solve this problem:
Call one of a heterogenous set of functors (their call operators might be templates) based on a runtime index with a complexity of O(log N) (basically what an n-ary tree structure of nested switch/case blocks does).
The solution o handles unary functors only and doesn't bother with the result (simplicity), o contains numerous workarounds and is far away from being perfect, o requires an MPL-patch [ http://tinyurl.com/ljfdm] to compile, but o nevertheless documents my fight with the library, hopefully including lots of mistakes a new user is tempted to make, so it might work good to inspire upcomnig examples.
http://tinyurl.com/l5bxl (source file in the vault)
Very cool! That might be a good example for a tutorial if you are willing to document and share it.
Sure (that is, for the willingness-part).
I'm not sure whether it qualifies for a good tutorial. There might be better ways to do things (I wanted to get my hands on the library quickly, so I didn't put too much time into planning, plus I still have some questions, below).
Right.
Given that my implementation can not be radically simplified, it might also be too much code for a tutorial. Maybe a linear version for a tutorial and the logarithmic version for an inline-documented source code example would work better...
BTW. implementation improvements, anyone? I'm all ear!
I was contemplating on something like the one you are doing. The inputs are: 1) A runtime value (a primitive integer; e.g. char,int) 2) A tuple of functions 3) A tuple of args (usually tiers) I was thinking of using the boost preprocessor instead to generate actual switch code. Something like: template <int Size> struct switch_dispatch; template <> struct switch_dispatch<1> { template <typename RT, typename Int , typename Functions, typename Args> static RT call(int n, Functions const& dispatch, Args const& args) { return at_c<0>(dispatch)(args); } }; template <> struct switch_dispatch<2> { template <typename RT, typename Int , typename Functions, typename Args> static RT call(int n, Functions const& dispatch, Args const& args) { if (n == 0) return at_c<0>(dispatch)(args); else return at_c<1>(dispatch)(args); } }; template <> struct switch_dispatch<3> { template <typename RT, typename Int , typename Functions, typename Args> static RT call(int n, Functions const& dispatch, Args const& args) { switch (n) { case 0: return at_c<0>(dispatch)(args); case 1: return at_c<1>(dispatch)(args); } } }; ++ A little change, we can use an mpl::vector_c to hold the cases. Something like: case mpl::at_c<cases, 0>::value : return at_c<0>(dispatch)(args); case mpl::at_c<cases, 1>::value : return at_c<1>(dispatch)(args); where "cases" is an mpl::vector_c. Such a utility will provide the backbone for 1) Phoenix2's switch_ statement 2) Spirit's switch_p 3) Spirit-2's predictive parsing schemes, and all those stuff that intends to optimize spirit's alternative. ++ Some more code to handle defaults; etc... see Phoenix2 switch and Spirit switch_p for reference. ... More comments on your post later. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net