
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). 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! So if we want to turn it into a source code example or tutorial, we should try to establish common practice. Therefore I'd like to ask you to comment on a few problems for which there might be a preferred/recommended solution: 1. How to set up the client namespaces most conveniently? Too many qualified names clutter my code. I actually like the scheme the library uses but I encountered following portability problems on the client side: namespace a_scope { using namespace boost::fusion; namespace result_of { using namespace boost::fusion::result_of; } namespace mpl = boost::mpl; struct a_copy_function; // omitted for transparency namespace result_of { template<typename Seq> struct noop_transform : transform<typename boost::add_const<Seq>::type, a_copy_function> // ^^^^^^^^^ vc 7.1 and gcc 3.4 choke here { }; } template<typename Seq> inline typename result_of::noop_transform<Seq>::type // ^^^^^^^^^ found ambiguous by some compilers // (IIRC it was gcc, couldn't reproduce the case, though) noop_transform(Seq const & seq) { return transform(seq, an_identity_function()); // ^^^^^^^^^ found ambiguous by vc 8 (visible + ADL) } } 2. Fusion and MPL placeholder expressions MPL placeholder expressions are very convenient for specifying the result because of their lazy nature (see lines 267, 312). Of course, this approach trades compile time for syntactic sugar. The syntactic sugar might not be entirely irrelevant, because it allows us to emphasize even complex problems with little code. So, I still wonder, whether it is a good idea to use MPL lambda for the result computation or not. Is it? If so (even occasionanlly), it would be necessary to have at least accessors for pair members (they are needed to keep the evaluation lazy, see line 211) or, ideally, if there would be a normalization between the STL and the MPL pair concepts (then MPL's accessors, 'first' and 'second', could be borrowed). (It would also be cool if one could just typedef the lambda expression to nested result or inherit from a wrapper. I don't know whether it's possible and a good idea - this part is just loud thinking)... 4. Choice of datastructures I used cons lists for the tree because I figured they might be limitless and because the structure is built one element at a time. There will be a lot of traversal later -- does it make a difference / would have 'vector' been a better choice? 5. BTW... I found it surprising that "iter->second" didn't work in place of "(*iter).second" (see lines 456, 485)... The other issues that require workarounds in the code have already been reported and acknowledged elsewhere in this branch of the thread.
In fact, I need something like that in Spirit-2 (but I need the result and more args).
In fact, it is Spirit-inspired [ spirit.devel, "self-adjusting alternative parser", bottom of the post ]. I used an unary functor with a void return for the example, but calling a function, adding another parameter and returning a bool value is nearly as trivial as its initial removal from the concept.
Fusion rocks!
Thanks! Kind words like that make all those long coding nights all worth while! :)
It must've been plenty, guessing from another 17218 lines of clean-looking & heavily templated code for the 'boost' directory... **** Another thundering applause **** Regards, Tobias