|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2003-04-15 09:07:14
"Paul Mensonides" <pmenso57_at_[hidden]> writes:
> None of these extensions are without precedent or are major extensions--except a
> scoping mechanism, which I added because what I've seen of the current idea is
> fundamentally flawed.
Here are some remarks I sent to David Vandevoorde after ruffling some
feathers in the extensions working group at the C++ committee meeting
by suggesting the same thing -- he offered to present some of them for
me to avoid misinterpretation. My original concerns were based around
PP metaprogramming but you will probably find the ones presented here
to be much more pedestrian. The notation and semantics below is based
on the last discussion I saw in the EWG, but I think the notation in
particular is still very fluid. BTW, I have some sympathy for the
idea of using scoping characters (like "{}") that can be matched by
existing editors.
--- How will macro scoping be used in real life? Let's take a look at a simple example. Assume header x.hpp defines exported configuration macros SOME_LIBRARY_X, SOME_LIBRARY_Y and SOME_LIBRARY_Z. Suppose I want to use that in a header a.hpp. One possibility is: a.hpp: #{ # ifndef A_INCLUDE_GUARD # define A_INCLUDE_GUARD # include "x.hpp" # in SOME_LIBRARY_X SOME_LIBRARY_Y SOME_LIBRARY_Z . . . # endif // A_INCLUDE_GUARD #} I have a concern about the amount of boilerplate code here. Now every modern header file will have 3 lines of boilerplate at the beginning and 2 at the end. It would be nice to be able to write: #scope (or something) at the beginning of the file, and have that be equivalent to all of the boilerplate. Another concern I have is that in order to avoid leaking the names defined in x.hpp, the user of x.hpp must not only #include it, but must explicitly "in" each of them. For libraries which require quite a few configuration macros, this can be terribly verbose. It would be nice to be able to just write: #include "x.hpp" and get all of its exported macros in the current scope. But how would that work? Let's look at x.hpp: x.hpp #{ # ifndef SOME_LIBRARY_X_INCLUDE_GUARD # define SOME_LIBRARY_X_INCLUDE_GUARD # include "z.hpp" . . . # define SOME_LIBRARY_X ... # define SOME_LIBRARY_Y ... # define SOME_LIBRARY_Z ... // here # endif // SOME_LIBRARY_X_INCLUDE_GUARD #} You might think you could just add # out SOME_LIBRARY_X SOME_LIBRARY_Y SOME_LIBRARY_Z at the comment marked "here", but think about what happens in this case: b.hpp: #{ # ifndef A_INCLUDE_GUARD # define A_INCLUDE_GUARD # include "x.hpp" # in SOME_LIBRARY_X SOME_LIBRARY_Y SOME_LIBRARY_Z // use SOME_LIBRARY_X/Y/Z to define void foo(bar) # endif // A_INCLUDE_GUARD #} c.hpp #{ # ifndef A_INCLUDE_GUARD # define A_INCLUDE_GUARD # include "c.hpp" // for void foo(bar) # include "x.hpp" // for config macros # in SOME_LIBRARY_X SOME_LIBRARY_Y SOME_LIBRARY_Z . . . # endif // A_INCLUDE_GUARD #} because of the #include guards in x.hpp, including it in c.hpp has no effect. Can the code in c.hpp see the SOME_LIBRARY_... config macros? -- Dave Abrahams Boost Consulting www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk