|
Boost : |
From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2006-05-11 13:19:05
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk