[Effective-cpp] Item 1: Uses and Abuses of vector

Terje Slettebø tslettebo at broadpark.no
Wed Oct 27 02:10:01 EDT 2004


>From: "Lois Goldthwaite" <lois at loisgoldthwaite.com>

> On Tuesday 26 October 2004 15:53, Terje Slettebø wrote:
> > >Adrian Fagg <adrianf at evaluategroup.com>:
> > > I know I'm in a minority here but I don't agree with the consensus
that
> > > all future enhancements should be in the standard libraries and not
> > > direct support for e.g. nested functions etc.
> >
> > I didn't know there was consensus about this (and I'd think the core and
> > evolution working groups would be rather surprised by it, as well, since
> > they work on core language changes for C++0x. :) ), and in any case, I'm
in
> > violent agreement with you. :)
>
> As a general principle, the C++ committee strongly favours library
solutions
> over unnecessary core language changes.
>
> 1) A library solution can be put to work almost immediately (even if the
> programmer has to write a home-grown version of it). Core language changes
> take several years to percolate to the customer.
>
> 2) The core language is so complex and interdependent that changing the
> compiler in one area is likely to destabilise support for some other bit
of
> it.

Naturally. This was not at least the reason for me bringing up a library
solution like BLL in the first place, and for enquiring about how core
language support might look like. It seemed to me that the BLL syntax was
quite clean, but, yes, for more complex code - as it has to be a single
expression - it can become rather complex.

Even with everything having to be an expression, it's quite amazing what you
_can_ write as a single expression. For example, have a look at
Boost.Spirit's subrules, or Phoenix (Spirit's lambda):

Subrule example
(http://spirit.sourceforge.net/index.php?doc=docs/v1_6/subrules.html):

    struct calculator : public grammar<calculator>
    {
        template <typename ScannerT>
        struct definition
        {
            definition(calculator const& self)
            {
                first =
                (
                    expression  = term >> *(('+' >> term) | ('-' >> term)),
                    term        = factor >> *(('*' >> factor) | ('/' >>
factor)),
                    factor      = integer | group,
                    group       = '(' >> expression >> ')'
                );
            }

            subrule<0>  expression;
            subrule<1>  term;
            subrule<2>  factor;
            subrule<3>  group;

            rule<ScannerT> first;
            rule<ScannerT> const&
            start() const { return first; }
        };
    };

"first" is a parsing rule consisting of four subrules ("expression", "term",
"factor" and "group"). As you can see, each subrule is terminated with a
comma, having the same use there as semicolon has for statements.

One could also express it as four rules, but as a "rule" collapses the type
information, this may be less efficient than the subrule version. The
subrule version - as it's all one expression - may tax the compiler quite
heavily though, and there's the issue of error reporting (where concept
support may help).

Phoenix example
(http://spirit.sourceforge.net/distrib/spirit_1_7_0/libs/spirit/phoenix/doc/
statements.html):

    for_each(c.begin(), c.end(),
        if_(arg1 > 5)
        [
            cout << arg1 << " > 5\n"
        ]
        .else_
        [
            if_(arg1 == 5)
            [
                cout << arg1 << " == 5\n"
            ]
            .else_
            [
                cout << arg1 << " < 5\n"
            ]
        ]
    );

:)

And you thought BLL was involved. ;) Phoenix also has support for "local
variables" and closures, all stack-allocated and therefore very efficient.

Anyway, I guess this strays quite far from the original topic (and list
topic). I just find it fascinating, is all. :)

> Having said that, the really interesting issues are at the boundary where
the
> core language and the standard library are both involved. So yes, core
> changes are being discussed, but certainly not just for the sake of
changing
> the language.

I don't think anybody thinks so, either. :)

> > My (admittably) simple example didn't use any binders, at all. Sure, for
> > more complex expressions, you may need them for Boost.Lambda, but I
think
> > the argument against the argument that if something can be done in the
> > library, it should be done in the library is a strawman, because I don't
> > think anyone claims this. If it can be done _well_ in the library,
perhaps,
> > and you may agree? (In other words, would you prefer std::complex to be
a
> > built-in type, or a library-provided one, for example?)
>
> Without the templates used in the library, std::complex would be several
> built-in types, as it is in C: complex_float, complex_double, etc. And
those
> types would be all that you could use. The library is extensible.

My point exactly.

After all, much of the aim of C++ is to provide core language support for
abstractions, supporting library development.

Regards,

Terje




More information about the Effective-cpp mailing list