Topic: Language support of precompiled headers
Author: dacut@henry.ece.cmu.edu (David A. Cuthbert)
Date: 1997/04/21 Raw View
Paul D. DeRocco <strip_these_words_pderocco@ix.netcom.com> wrote:
>Fergus Henderson wrote:
>> Nope, Ilia's suggestion did not outlaw any existing code.
>> Ilia's suggestion was to add a new `$include' directive that
>> had different semantics to the existing `#include' directive.
>I didn't mean to suggest it outlawed existing code. I was saying that it
>didn't look that useful to me, since it eliminates some of the very
>capabilities that people actually use headers for. People don't use
>headers merely to take some declarations and put them into a separate
>file. They use them to allow the same declarations to be used in large
>numbers of unrelated programs.
The reason why this has happened is that C (and, therefore, C++) uses
pure textual file inclusion and macro substitution (at least for
project-specific headers; things like <iostream>, etc., can exist as
precompiled headers, etc.). Depending upon your perspective, this
either opened back doors or provided additional functionality in the
type system.
I don't see a way around this in C. C++, however, provides a number
of additional features (static const class members and templates)
which should eliminate the need for such pre-processor hacks.
>And in the real world, different programs
>need to steer the interpretation of headers to some extent, by defining
>different preprocessor symbols. An $include directive that specifically
>disallowed that would, in my view, be a directive of fairly limited
>usefulness. However, I'm willing to be proved wrong, if you have a good
>counterexample.
Consider the assert macro, one implementation of which might be:
#if !defined(NDEBUG)
#define assert(t) if(t) abort()
#else
#define assert(t) (void)(0)
#endif
A good C++ compiler should compile the following just as efficiently
(though I can imagine many current compilers, which have not-so-
debugged implementation of templates, generating inefficient code):
template<bool assertEnable>
inline void assert(bool test) {
if(assertEnable && test)
abort();
}
Using this is straightforward:
#include <assert>
static const bool useAsserts = false;
int myFunction(std::vector<int> listOfInts) {
assert<useAsserts>(listOfInts.size() > 3);
// ...
}
On the whole, I'm not a big fan of the C preprocessor and would like
to see all # directives eventually eliminated. If I were to design a
language and base it loosely on C++, I think that #pragma might be the
only one to survive (and highly discouraged).
--
David A. Cuthbert (henry.ece.cmu.edu!dacut)
Graduate Student, Electrical and Computer Engineering
Data Storage Systems Center, Carnegie Mellon University
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/22 Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
>... in the real world, different programs
>need to steer the interpretation of headers to some extent, by defining
>different preprocessor symbols.
I think "need" is too strong here. People often do it in C, because
it's convenient. But there are other languages that don't provide
that sort of functionality, and people using those other languages
seem to get by without much trouble.
>An $include directive that specifically
>disallowed that would, in my view, be a directive of fairly limited
>usefulness. However, I'm willing to be proved wrong, if you have a good
>counterexample.
I don't know whether you would consider Ada to be a good counterexample ;-)
But to take a fairly common C/C++ example, with most implementations
it's easy to use `-I' options rather than `-D' options to steer the
interpretation of headers. For example, if you have
standard-conforming headers, and headers with extra symbols, the
headers with the extra symbols can be defined by
/* std/stdio.h */
int printf(const char *, ...);
/* extension/foo.h */
#include <std/foo.h>
void clearscreen(); /* clear the console */
int gotoxy(int x, int y); /* position cursor at (x,y) */
I'm willing to be convinced of the usefulness of using #defines
and #if to steer the interpretation of headers, if you have good
enough examples. But I think for most purposes you don't need that
functionality.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/22 Raw View
Tony Cook wrote:
>
> The reliance of the 16-bit headers on memory model isn't much of a
> problem, since I would assume that in such a scheme the 'environment'
> macros defined by the compiler (__LARGE__ for -ml in BC++ for example)
> would still be defined, just as __LINE__ and __FILE__ would still be
> defined.
Borland goes a step further in their RTL headers (albeit not in
windows.h), allowing the caller to specify different calling
conventions, in cast the programmer wants to recompile the library a
different way.
Anyway, there is a tradeoff between the desire to do as much
"compilation" in advance, which is the whole point of precompiled
headers, and the fact that changes in the caller's environment limits
how far you can compile without analogous changes being reflected in the
compiled output.
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/23 Raw View
David A. Cuthbert wrote:
>
> A good C++ compiler should compile the following just as efficiently
> (though I can imagine many current compilers, which have not-so-
> debugged implementation of templates, generating inefficient code):
>
> template<bool assertEnable>
> inline void assert(bool test) {
> if(assertEnable && test)
> abort();
> }
>
> Using this is straightforward:
>
> #include <assert>
> static const bool useAsserts = false;
>
> int myFunction(std::vector<int> listOfInts) {
> assert<useAsserts>(listOfInts.size() > 3);
> // ...
> }
(Why the template? Why not just test the constant inside the inline
function?)
You're certainly right that there are still many things that are done
with the preprocessor that could be done without, especially now that we
have templates.
But even the above case, if you want it to compile into the most
efficient code (i.e., not bothering to compute "listOfInts.size() > 3"
if assertEnable is false), then there's a limit to how much
pre-compiling you can do. Ideally, you'd like to compile to object code,
but you can't because you want certain object code completely left out
under some circumstances. So how far can you compile? In this case, you
could compile as far as the symbol table and parse tree, or maybe a tad
further. In some other situations, you can't even compile that far, but
can only go as far as the token stream. And where token pasting is used
(ugh), you can't even do that!
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/23 Raw View
Fergus Henderson wrote:
>
> "Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
>
> >An $include directive that specifically
> >disallowed that would, in my view, be a directive of fairly limited
> >usefulness. However, I'm willing to be proved wrong, if you have a good
> >counterexample.
>
> I don't know whether you would consider Ada to be a good counterexample ;-)
Well, I meant a counterexample concerning C++.
> I'm willing to be convinced of the usefulness of using #defines
> and #if to steer the interpretation of headers, if you have good
> enough examples. But I think for most purposes you don't need that
> functionality.
One change that would make it less necessary to use #defines would be to
allow any declaration that wasn't also a definition to be repeated. I
see lots of crud like this in headers:
#ifndef _DIV_T
#define _DIV_T
typedef struct {
int quot;
int rem;
} div_t;
#endif
so that the structure can be defined in more than one header. Why not
just allow the typedef to be repeated, as long as it's identical?
Another common use is for handling multiple memory models:
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
typedef long ptrdiff_t;
#else
typedef int ptrdiff_t;
#endif
#endif
If you want your precompiled header to be more than just a binary token
string or a binary parse tree, then you really need separate versions
for the two sizes of ptrdiff_t, since the two sizes can result in
dramatically different code.
This is all becoming less and less important, I think, simply because
computers are getting faster and faster. Current precompiled header
technology on a nice fast Pentium is plenty fast, in my view, so I don't
particularly bemoan the lack of the hypothetical $include directive that
sparked this thread.
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/04/23 Raw View
dacut@henry.ece.cmu.edu (David A. Cuthbert) writes:
|> >And in the real world, different programs
|> >need to steer the interpretation of headers to some extent, by defining
|> >different preprocessor symbols. An $include directive that specifically
|> >disallowed that would, in my view, be a directive of fairly limited
|> >usefulness. However, I'm willing to be proved wrong, if you have a good
|> >counterexample.
|>
|> Consider the assert macro, one implementation of which might be:
|>
|> #if !defined(NDEBUG)
|> #define assert(t) if(t) abort()
|> #else
|> #define assert(t) (void)(0)
|> #endif
But this is not a legal implementation. The expansion of the assert
macro must be an expression.
|> A good C++ compiler should compile the following just as efficiently
|> (though I can imagine many current compilers, which have not-so-
|> debugged implementation of templates, generating inefficient code):
|>
|> template<bool assertEnable>
|> inline void assert(bool test) {
|> if(assertEnable && test)
|> abort();
|> }
|>
|> Using this is straightforward:
|>
|> #include <assert>
|> static const bool useAsserts = false;
|>
|> int myFunction(std::vector<int> listOfInts) {
|> assert<useAsserts>(listOfInts.size() > 3);
|> // ...
|> }
But it doesn't have assert's functionality, far from it. One of the
important points about assert is that I can turn it off and on within a
file, by #undef NDEBUG/#define NDEBUG and reincluding <assert.h>.
This isn't to say that this is the only way of achieving this end, or
even the best way. Using your technique, for example, I could have
several distinct assertion functions: assert< userError >, assert<
internalError >, etc. which were turned on and off separately. Or with
a slight modification, levels of assertion:
static const int assertionLevel = errorsAndUp ;
assert< assertionLevel >( warning , condition1 ) ;
assert< assertionLevel >( critical , condition2 ) ;
|> On the whole, I'm not a big fan of the C preprocessor and would like
|> to see all # directives eventually eliminated. If I were to design a
|> language and base it loosely on C++, I think that #pragma might be the
|> only one to survive (and highly discouraged).
In practice, the only use of preprocessor directives other than #include
that appears in my code is conditional compilation on the
absense/presence of different language features. Hopefully, these will
disappear when we have a standard.
This doesn't mean that I don't have system dependancies, but that
generally, I handle them by encapsulating them in a separate class, in a
separate file, in a separate directory. A -I with the system dependant
directory brings in the correct version of the headers. (For most of
the larger aspects -- reading directories, etc. -- I will work behind a
class firewall. The interface, defined in the include file, is not
system dependant, and the only time I have to pull in the system
dependant files is when compiling the implementation.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/04/23 Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
|> I'm willing to be convinced of the usefulness of using #defines
|> and #if to steer the interpretation of headers, if you have good
|> enough examples. But I think for most purposes you don't need that
|> functionality.
You don't need it, but it does make code maintenance easier. A simple
example: I use the -I option to pull in the correct machine file, but
this file only defined things like GB_HASEXCEPTIONS, etc. It is
included from a global file, which contains:
#if GB_HASEXCEPTIONS
#define GB_BEGIN_TRY try {
#define GB_END_TRY }
#define GB_CATCH( cond ) } catch( cond ) {
#define GB_RETHROW throw
#else
#define GB_BEGIN_TRY if ( 1 ) {
#define GB_END_TRY }
#define GB_CATCH( cond ) } else if ( 0 ) {
#define GB_RETHROW
#endif
Obviously, I could move all of the definitions into the machine file,
and avoid the #if. But there are around a hundred lines of them, in
all, and it is, IMHO, preferable to keep the machine file as simple as
possible (about 20 or thirty lines, almost all of the sort: "#define
GB_HASxxxx 0"). Duplicating the above in 20 or 30 machine files seems
too error prone to me.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1997/04/23 Raw View
David A Cuthbert writes:
> template<bool assertEnable>
> inline void assert(bool test) {
> if(assertEnable && test)
> abort();
> }
you probably meant && !test, right?
> Using this is straightforward:
> #include <assert>
> static const bool useAsserts = false;
> int myFunction(std::vector<int> listOfInts) {
> assert<useAsserts>(listOfInts.size() > 3);
> // ...
> }
Well, not so straightforward... Here are some simpler (IMHO)
mechanisms:
The header file might define an assert function that takes two
arguments:
inline void assert(bool test, bool enable) { /*...*/ }
then users might redeclare assert to have a default value for the
second argument:
inline void assert(bool, bool = true);
Or assert could use a standard variable name as the default argument:
inline void assert(bool test, bool enable = useAssert) { /*...*/ }
So that users would have to declare useAssert and then include
<assert>:
static const bool useAssert = true;
#include <assert>
These alternatives, though, have the same problem of yours: the
condition is always evaluated, unless it can be inlined and known not
to have any side effects. This could be prevented if assert were a
function that returned bool:
inline bool assert(bool test) {
if (!test)
abort();
return test;
}
Then it would be used like this:
useAsserts && assert(something);
Unfortunately, none of these is as simple and as efficient as the
standard C assert macro...
--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br mailto:aoliva@acm.org
Universidade Estadual de Campinas, SP, Brasil
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willer@interlog.com (Steve Willer)
Date: 1997/04/25 Raw View
dacut@henry.ece.cmu.edu (David A. Cuthbert) wrote:
>template<bool assertEnable>
>inline void assert(bool test) {
> if(assertEnable && test)
> abort();
>}
This is missing two pretty important features of assertions: The ability
to dump the file and line number on assertion failure, and the ability
to display the expression on assertion failure. It also behaves
differently from the current assert in another way: In your example, the
test expression is always evaluated. This cannot be optimized out, and
can generate different side-effects from the existing assert.
----
Steve Willer
http://www.interlog.com/~willer/
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/18 Raw View
Ilia Zemskov wrote:
>
> Abstract
>
> In this article author suggests one direction of the C++ evolution
> - a language support of precompiled headers. Author explains idea and
> new C++ language constructions to provide better use of precompiled
> headers with C++ projects and shows benefits of this language
> improvement.
[etc.]
It seems that in the effort to make headers independent of the context
in which they are included, you've outlawed one of the main things that
people actually do with headers, which is to use previously defined
symbols to steer the interpretation of the header. The windows.h header
is full of this stuff, especially the 16-bit version which has to deal
with different pointer modifiers depending upon the memory model, etc.
--
Ciao,
Paul D. DeRocco
(Please send e-mail to mail:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/19 Raw View
"Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com> writes:
>Ilia Zemskov wrote:
>>
>> In this article author suggests one direction of the C++ evolution
>> - a language support of precompiled headers. Author explains idea and
>> new C++ language constructions to provide better use of precompiled
>> headers with C++ projects and shows benefits of this language
>> improvement.
>
>It seems that in the effort to make headers independent of the context
>in which they are included, you've outlawed one of the main things that
>people actually do with headers, which is to use previously defined
>symbols to steer the interpretation of the header.
Nope, Ilia's suggestion did not outlaw any existing code.
Ilia's suggestion was to add a new `$include' directive that
had different semantics to the existing `#include' directive.
Ilia's `$include "blah.h"' suggestion was in fact not that dissimilar to
Bjarne Stroustrups recent idea of an `include blah;' declaration.
I think that of all the criticisms in Ian Joyner's C++ critique, the
lack of a proper module system is C++'s worst weakness. Bjarne suggested
a possible solution to this problem, but unfortunately the timing was not
good. C++ is already complicated enough, and the time for major extensions
like this has passed.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1997/04/21 Raw View
Paul D. DeRocco (strip_these_words_pderocco@ix.netcom.com) wrote:
: It seems that in the effort to make headers independent of the context
: in which they are included, you've outlawed one of the main things that
: people actually do with headers, which is to use previously defined
: symbols to steer the interpretation of the header. The windows.h header
: is full of this stuff, especially the 16-bit version which has to deal
: with different pointer modifiers depending upon the memory model, etc.
I don't think I'd use the monolithic 16-bit windows.h as an example of
good programming practice.
The 32-bit headers are better organized in that they are split up on
sub-system boundaries (winuser.h, wingdi.h etc), but they also define
large numbers of macros.. which don't follow the normal C/C++
convention for using upper-case only.
The reliance of the 16-bit headers on memory model isn't much of a
problem, since I would assume that in such a scheme the 'environment'
macros defined by the compiler (__LARGE__ for -ml in BC++ for example)
would still be defined, just as __LINE__ and __FILE__ would still be
defined.
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/21 Raw View
Fergus Henderson wrote:
>
> Nope, Ilia's suggestion did not outlaw any existing code.
> Ilia's suggestion was to add a new `$include' directive that
> had different semantics to the existing `#include' directive.
I didn't mean to suggest it outlawed existing code. I was saying that it
didn't look that useful to me, since it eliminates some of the very
capabilities that people actually use headers for. People don't use
headers merely to take some declarations and put them into a separate
file. They use them to allow the same declarations to be used in large
numbers of unrelated programs. And in the real world, different programs
need to steer the interpretation of headers to some extent, by defining
different preprocessor symbols. An $include directive that specifically
disallowed that would, in my view, be a directive of fairly limited
usefulness. However, I'm willing to be proved wrong, if you have a good
counterexample.
--
Ciao,
Paul D. DeRocco
(Please send e-mail to mail:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Ilia Zemskov" <zemskov@ashtech.msk.ru>
Date: 1997/04/17 Raw View
[Moderator's note: Despite the author's note at the beginning of this
message, it isn't actually crossposted. This article was submitted
to, and is accordingly posted to, comp.std.c++ only. mha]
CROSSPOSTED TO:
comp.lang.c++
comp.lang.c++.moderated
comp.std.c++
relcom.fido.su.c-c++
Fresh idea: C++ language support of precompiled headers
-------------------------------------------------------
Abstract
In this article author suggests one direction of the C++ evolution
- a language support of precompiled headers. Author explains idea and
new C++ language constructions to provide better use of precompiled
headers with C++ projects and shows benefits of this language
improvement.
*******
Almost all C++ programmers know what is "precompiled headers". But
let me give here a short description of this technique of software
development (you may want to skip this description). So, some good C++
compilers, for instance, latest versions of Borland C++ and Microsoft
Visual C++, have feature called "precompiled headers", which helps to
reduce compilation time of projects with many source files and large
headers. In this article author will use abbreviation PH for "precompiled
headers".
With PH compiler compile header only once and then use results
during compilation of sources, which include it. It's seems to me that
it is work in following manner. When compile given header (.h) file
first compiler creates (updates) a large binary file called "precompiled
header" where it stores type and data definitions from header. After
that, when compiler compile source (.c or .cpp) file, it use this
definitions instead of recompiling header file again.
But there are some inconvenient limitations: for example, header
files to precompile "must" to be included in the same order in all
source files; all source files should have equal defines which affect
headers, etc. Compilers never check this limitations and this is
inconvenient too. Really it is true limitations only for headers
depended on each other.
This explanation of PH is not very clear, so, I recommend to readers
who are unfamiliar with precompiled headers technique to become
acquainted with it - not only to understand this article but to improve
your own design facilities. For example, such readers can look at the
documentation for compilers which support PH.
Well, now my proposal. The programming language should provide
support of precompiled headers. Why there is no such useful feature
in C++ ? It has all that designer of objects may want, but not programmer.
Author thinks that the root of evil is in imperfect preprocessor. So,
to make it perfect we need at least to include preprocessor in the C++
language. There will no any harm of this because C/C++ preprocessor
is the de-facto standard.
To provide the support of precompiled headers author suggests new
preprocessor directive called "$include directive". Author thinks that
it may be syntax construction such as:
$include {
<file1.h>
<file2>
"userfile.h"
...
}
Author will explain the semantics of this directive. Let us define
term "definition" as one of the type definition, symbol defined by
#define directive or data definition. We will use this meaning of
"definition" only to explain the semantics of suggested directive.
$include directive may appears in both .cpp and .h- files. All
definitions from header included by the $include directive are visible in
point of $include. Its semantics looks like the semantics of #include
directive, but:
(1) inside header included by $include directive the only visible
definitions are definitions defined (declared) in this header or in
headers included to this header by either $include or #include
directive. So, such header is not affected by any other header unless
other header is included in it;
(2) all headers inside $include directive don't use values of any
external #define directives but only values, defined from command line
of compiler.
Perhaps it is better to illustrate condition (1) by code
example bellow.
// ---------- File hdr.h ---------------
typedef int * pint;
// ---------- End of file hdr.h -------------
// ---------- File src.cpp ---------------
#define int {}
$include
{
"hdr.h"
}
pint Variable; // "pint" is int *
main() int // "int" is redefined to {}
// ---------- End of file src.cpp -------------
In this example keyword "int" is not redefined in the file "hdr.h"
but it is redefined in file "src.cpp" below #define directive.
With such preprocessor facility C++ program will not be linear as now
it is. It will like tree; source file will play role of root and headers
will play role of other nodes.
Now author want to define the term "standard header precompilation".
Let us a future C++ compiler will have mode (or command- line switch)
of standard header precompilation and (optionally) mode of non-
standard header precompilation. In the last mode it may precompile
headers in any way. In mode of standard header precompilation it will
use the following rules:
(important rules)
1) compiler will never precompile headers with #include
directive(s) inside their;
2) compiler will precompile all headers included by $include directives
as well as headers included to this headers by $include directive
(recursively), if rule 1) is not applicable;
(less important rules)
3) inside either .cpp or .h-file an appearance of both $include and
#include directives of the same header is an error;
4) if .cpp file have both $include and #include directives for
different headers then it's OK, but, of course, only headers, included
by $include directives will be precompiled.
When create precompiled header, compiler must store for every
definition name of header, which is included in source file and where
this definition is visible. Compiler must verify that source file include
header before it make visible definitions from header in source file.
As usual compiler must generate error messages for mismatch duplicate
definitions.
As described above, $include directive is a way to force headers to
be not dependent from each other. So, with this language extension and
appropriate compiler programmer may use $include directive to include
headers to his sources in every order and precompile them. He is
allowed to suppress unnecessary headers to include. He should not also
worry about different defines before different includes of headers,
only he should take care that all defines from command line are equal
for all sources.
Why C++ should provide this support ? The list of reasons, probably
incomplete, is bellow.
1) With this new feature you will be able to precompile headers for
the same source code with different compilers and/or on different
platforms.
2) If you have a large project you may want to precompile user-
written headers. With $include directive it will be much convenient.
3) With "nonstandard header precompilation" you may, of course ,
precompile headers for system libraries (such as <windows.h>). But if
you will precompile headers for several system libraries, you should
precompile the equal set of headers for all your sources or you will
have no warranty that you project will be compiled correctly. It is
inconvenient, especially for sources and headers, which are shared
between different projects.
4) In general: you can precompile headers now, but sometimes it
is hard. With language support it will much easier.
5) Many C++ compilers, for example GCC, have not precompiled headers
because of it is a non- standard feature. When it will be standard
feature, they will have.
Author hopes that C++ designers and the C++ community will be
attracted by this idea and, may be, by the suggested way of its
implementation.
With best regards,
Ilya Zemskov e-mail: zemskov@ashtech.msk.ru
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]