
Thanks for your responses, David. On 12/12/2004 08:16 PM, David Abrahams wrote:
Larry Evans wrote: [snip]
I believe is much simpler to understand and doesn't use any preprocessor macros.
Yes, but it is much less efficient for some applications.
OK. I was under the (probably mistaken) assumption that speed of access to the elements was essentially the only speed createria, and I couldn't imagine anything faster than: factor<...,Index>::my_field; where Index the enumeration index (an element of Indices in template < Indices, TypeMap<Indices> product; ) and factor<...,Index> is the Index-th superclass of the product. When I tried to see how fusion tuples did it, I couldn't easily because of the boost/preprocessor macro use. However, since your earlier post said it was a "flat" structure, I assumed the fusion tuple has instance variables: T0 my_0; T1 my_1; ... Tn my_n; generated by macros, and that access methods were generated similarly, i.e. a get<I,tuple> general template and a preprocessor generator of specializations. OOPS, that means the tuple size would have to be available for the preprocessor. So, I looked at tuple.hpp then at tuple_builder.hpp, then at get_tuple_n<n> ... then I gave up :(
The fusion design was carefully refined for both runtime and compile-time speed. It is a complete hybrid compile-time/runtime framework just like the MPL is a complete compile-time framework, and it integrates well with MPL (every fusion sequence is also an MPL sequence).
This is probably one place where indexed_types break down wrt MPL because I didn't consider making each product an MPL sequence.
This wasn't just done lightly; it's the result of a careful and comprehensive design process.
As I and everyone else expected. Could you remember or have a record of the reason's why the non-flat structure and use of indexed supertypes was less than optimal?
I'm guessing that the "flatness" of fusion tuples is done by simply creating different field names with corresponding types by means of preprocessing macros.
Understanding the implementation of fusion isn't important, except to its maintainer.
It might more easily reveal the reasons why the flat implementation is more optimal than ae non-flat one.
However, in addition, if variant (i.e. sum) is thrown onto the scales, then I believe easier undestanding wins.
Maybe you're not the best judge of easy understanding.
I completely agree. I believe it's pretty typical that the coder initially believes his code is easier to understand than reviewers would say. However, I'd guess that one attempting to understand product would simply look at the project<Index> code, then at the factor<,, Index> superclass to find my_field of type TypeMap<Index>::type and understand product. OTOH, as reflected in my previous response terminated with :( , understanding how tuple accessed the selected fields seemed much harder, at least to me. Maybe you could give a brief description of the thought process you went through in understanding product.
What does variant have to do with sum? It's completely non-obvious to me.
Well, maybe that's part of the problem. Are you assuming sum has something to do with numbers. I'd meant it to mean disjoint sum applied to types, and of course variant does model disjoint sum. Is that the reason for the disconnect (of our mutual understanding) ?
In addition, I think sum can be modified by adding:
term<...Index>::accept(visitor&a_viz) { if(index() == Index) { a_viz(mpl::int_c<Index>(), project<Index>());} else { term<...,Index-1>::accept(a_viz);} }
which is essentially the visitor pattern.
You've lost me completely.
Well, I had assumed you'd looked at sum.hpp and could see that term<...Index> was one of the sum superclass's representing the Index-th possible type of the disjoint sum. The accept corresponds to the concrete version of the virtual accept in the Element participant in the visitor pattern. However, there is a typo above which contributed to the confusion, I'm sure. The line: { a_viz(mpl::int_c<Index>(), project<Index>());} should really be: { a_viz.visit(mpl::int_c<Index>(), project<Index>());} i.e. the Visitor participant visits the concrete element by using it's visit member function tailored to the concrete Element type argument, which is supplied by the concrete Elements accept method. IOW, The abstract Element participant corresponds to the sum in sum.hpp. The ConcreateElement participants correspond to the various "terms" in the disjoint sum and I got a working version now. I'll upload to sand-box if you'd think that might help.
What I'm also searching for is something that satisfies:
list<T> == sum<null_type, product<T,list<T>*>
[snip]
like or similar to the way the disjoint sum and cartesion product are used in textbooks to define a linked list. [snip] still lost.
I was trying to convey something similar to the line: rec(X.Unit+(A*X)) in: http://www.cs.cornell.edu/Info/People/sfa/Nuprl/NuprlPrimitives/Xrec_type_do... where Unit corresponds null_type (i.e. void* AFAICT ) and + is disjoint sum operator and * is the cartesian product operator. HTH. Regards, Larry