Boost logo

Boost Users :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-04-02 18:44:19


Markus Werle wrote:
> [ Sorry, gmane was down on Friday and I could not get access to another
> nntp access point during weekend ]
>
>
> Eric Niebler <eric <at> boost-consulting.com> writes:
>
>> Markus Werle wrote:
>>> So what we really need together with the tutorials and the
>>> documentation is a wiki about the design and evolution of boost.
>> Design rationales are good. A wiki might work, but a better place
>> might be in a "Rationale" section in each Boost library's documentation.
>
> The advantage of a wiki (or any other public read/write access
> documentation) is that not only the designer of some boost part is
> in the role of an author for his design rationales but others can
> easily contribute.

True dat.

> More important than the design rationale for boost::XXX is the
> design rationale for some of the building blocks of it, and since these
> are used across several distinct library parts, we really need
> design rationales for _techniques_ used in boost, a meta-boost design
> rationale.
> (Common tricks like deep_copy in all its flavours etc.)
>
> I sometimes come across a discusion which I feel to be important enough
> to be cut'n'pasted to a CMS, let it be wiki or joomla or whatever you
> like ...

Well, Boost has as wiki, so what's stopping you? :-)

>>> Then Eric Niebler could explain in depth why he needs
>>> "static, aggregate initialization" in proto
>>> (see
> <http://thread.gmane.org/gmane.comp.parsers.spirit.devel/2886/focus=2890
>> )
>>> and why mpl does not fit for proto.
>> Static initialization in proto is important so that when DSEL authors
>> declare their global primitives like _1, there are no global
>> initialization order problems.
>
> My skills are not such that this piece of information suffices
> as explanation about what was suboptimal and what was fixed.
> Going back to your code again ... maybe I catch the idea sometimes.
> Never saw that trick before.
>
> What is better in
>
> static type call(Expr const &expr)
> {
> type that = {proto::arg(expr)};
> return that;
> }
>
> than
>
> static type call(Expr const &expr)
> {
> type that = proto::arg(expr);
> return that;
> }
>
> ?

Oh, nothing at all. The benefit comes when declaring global primitives.
Consider this at namespace scope:

namespace my {
   struct placeholder {};
   proto::terminal<placeholder>::type const _ = {{}};
}

If terminal<>::type were a type with a constructor, that constructor
would have to run *sometime* and the placeholder wouldn't be usable
until after that time. Trouble is, C++ makes very few promises about
when that *sometime* is. In contrast, the code above requires no runtime
initialization. The placeholder just *is*, and there is no time during
your program's execution when it is invalid to use it.

>> The only problem I had using MPL with proto was compile-time
> performance
>> problems when using MPL lambdas.
>> In order to keep compile times down,
>> I've replaced as much template meta-programming in proto as possible
>> with preprocessor meta-programming.
>
> Could you publish an article about that?
> Your article "Conditional Love: Foreach
> Redux" (http://www.artima.com/cppsource/foreach.html)
> is a good example about cool things that are hidden in some
> innocent looking piece of code. Reading the header file never would
> have exposed the things that matter (at least to me).

I don't think that would make for an interesting article. See below.

>> And proto is a bit of a special case
>> since TMP-heavy libraries are built on top of proto, so the TMP
> overhead
>> of proto itself should be as small as possible. MPL is a very nice
>> abstraction, but it's not free. Ditto for Fusion.
>
> This raises 2 questions for me:
>
> 1. Could these issues be fixed for mpl and fusion or are you really
> forced to create your own enhanced versions?

I'm not creating enhanced versions of mpl or fusion. I'm using the
preprocessor to generate code that would do the same thing as an mpl or
fusion algorithm invocation. More below ...

> 2. If you build your own high performance versions of typelist etc.:
> isn't fusion and/or mpl a good place to add them instead to "hide" them
> in proto - below xpressive?
>
> <cite url="http://thread.gmane.org/
> gmane.comp.parsers.spirit.devel/2886/focus=2890">
> > [...] proto::basic_expr<> is the central data container of proto.
> > It's functionality very much resembles a fusion sequence
> </cite>

I think I've been unclear. In proto, I try to keep template
instantiations down. One way I do that is by generating specialization
with Boost.PP instead of calling mpl/fusion algorithms. Consider
deep_copy(), which essentially applies a transform to each child of a
node. There are at least two ways to do this:

1) The Easy Way: Use fusion::transform(). Done!

2) The Hard Way: write N specializations of deep_copy<Node> (where N is
the maximum number of children a node can have), and do the
transformation on each child directly.

The only thing (2) has going for it is that it incurs fewer template
instantiations. No fusion iterators, or transform_views, or
miscellaneous traits like begin<>, end<>, equal_to<>, or anything else.
But would I endorse (2)? No. Just like I wouldn't recommend programming
in assembly, unless you really need that extra 5% speed.

>
>> And yes, I measure compile time performance and don't optimize
>> prematurely.
>
> I do not question what you are doing.
> I am simply looking forward to profit from the fact that you've been
> already there in compiler hell and are willing to give us some good
> advice how to survive when we go there, too.
>
> I am probably asking too much here. It's only that I am not
> able to extract this knowledge from source code ...

I'm sorry to disappoint you, but there is probably no way you can profit
from proto's innards.

> P.S.:
> Apropos proto: are you planning to introduce a glommable disambiguation
> mechanism [Geoffrey Furnish]?

I Googled this: http://www.adtmag.com/joop/carticle.aspx?ID=627. IIUC,
this is a way to control which sub-expressions can combine with which
others, and with which operators. Proto can do this, and its mechanism
is much more powerful and elegant, IMNSHO. You define the meta-grammar
of your DSEL, and then you tell Proto that only expression types that
conform to that meta-grammar are allowed. Operators that produce invalid
expressions are not even considered.

First read this ("Patterns and Meta-Grammars"):
http://tinyurl.com/3akbtb

Then this ("Extending Proto"):
http://tinyurl.com/2xs222

HTH,

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net