Topic: #pragma once
Author: neil@REMOVETHISdaikokuya.co.uk ("Neil Booth")
Date: Thu, 2 Jan 2003 06:48:23 +0000 (UTC) Raw View
On Tue, 22 Oct 2002 15:34:42 +0000, James Kanze wrote:
> The rule is actually very much simpler. If the first preprocessor
> tokens after the file is opened are # followed by [if|ifdef|ifndef], the
> preprocessor memorizes the line. If the file has an associated
> memorized line, and the last preprocessor tokens when processing it are
> # endif, the preprocessor notes this fact, along with the memorized line
> (probably by putting the memorized line in a
> map<filepath,memorizedLine>). Whenever the preprocessor encounters an
> include directive, it checks to see whether it has a memorized first
> line for it. If so, it evaluates that line; if the evaluation results
> in a block which would be skipped, it doesn't even open the file.
Actually, it's not so simple (though I know of at least one compiler
that is buggy because it does what you've stated above).
You have to worry about #elif and #else, which invalidate the
optimization. I documented what I implemented in GCC at
http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html#Guard%20Macros
As a QOI issue, it's nice to have it work for #if !defined()
as well; I think a good proportion of headers do this. This
introduces the additional subtlety that you have to worry about
the #if expression being a macro (or containing macros) that
expand to the !defined() expression. Since those macros could
be redefined before a subsequent inclusion, it is not correct
to do the optimization in this case either. [Unless you want
to track those macros too, which is overkill.]
Neil.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 11 Nov 2002 17:07:34 +0000 (UTC) Raw View
Hyman Rosen wrote:
> Ada does not define any relationship between packages and files.
Just to amplify, many older Ada compilation systems used a program
library consisting of a proprietary repository of compiled code.
When you submitted a file to be compiled, whatever subunits it
contained would then be stored in the library, and the compiler
would look for the specifications and bodies of packages and
subprograms in there. Ada has strict requirements for compilation
order to ensure that changes are properly propogated so that no
program will be built with a module which is out of date with
respect to its source.
GNAT instead uses a source-code only scheme, but requires that
each package specification, package body, and standalone subprogram
live in its own file. It uses a standard naming convention which
can be overridden by a configuration file which gives the alternate
program name to file name mapping. It also comes with a utility
(gnatchop) which will split a file into multiple files to follow
this convention.
It would be nice if C++ had some sort of module system, but it
seems difficult to fit it into normal C++ style, which aside from
classes consists of groups of global items (functions, classes,
templates) which work together. One possibility that occurs to
me is given a 'using name;' declaration, to allow the compiler to
automatically seek out the declaration of 'name' rather than
require it to already have been seen.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 6 Nov 2002 01:15:48 +0000 (UTC) Raw View
In article <7f2735a5.0211041532.5b1579d7@posting.google.com>, Allan W
<allan_w@my-dejanews.com> writes
>Junior guru question: how long would a printable module name have to
>be, in order to have approximately
>340,282,366,920,938,463,463,374,607,431,768,211,455
>different possible values? (For some reasonable meaning of the word
>"reasonable" -- but in no case less than 90% of this number). Assume
>that we will use uppercase and lowercase letters, digits, and the
>underscore (_) only. (For now we'll ignore details such as whether the
>first character can be an underscore or digit.)
>
>Hint: 26+26+10+1=63 different characters. If identifiers are
>1 character long, there are 63 possibilities. For 2-character
>identifiers, there are 63*63 possibilities, and so on.
>N-character identifiers have 63**N possibilities, where ** is
>exponentiation ("to the power of").
>
>Advanced guru question: Without bothering to compute the exact odds,
>let's just take it as a given that the average module length will be
>FAR less than this lofty goal. Instead, visit Hades and locate a
>snowball, then come back and compute the odds of even 10 major players
>(not counting compiler vendors, complaince testers, and magazine
>reviewers) using a module length this long, for any reasonable
>definition of the word "major".
I am completely lost that somewhat long number consisted of 39 digits,
so any module with more than 39 chars in it massively exceeds that
number in potential values. More precisely 39 digit numbers are
approximately 2^129 and a single char restricted to the digits, letters
and _ can represent 2^6 so we need a string of roughly 22 chars.
Now the real problem is that module names are NOT normally randomly
selected.
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 6 Nov 2002 23:28:03 +0000 (UTC) Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> Allan W <allan_w@my-dejanews.com> writes
> >Junior guru question: how long would a printable module name have to
> >be, in order to have approximately
> >340,282,366,920,938,463,463,374,607,431,768,211,455
> >different possible values? (For some reasonable meaning of the word
> >"reasonable" -- but in no case less than 90% of this number). Assume
> >that we will use uppercase and lowercase letters, digits, and the
> >underscore (_) only. (For now we'll ignore details such as whether the
> >first character can be an underscore or digit.)
> >
> >Hint: 26+26+10+1=63 different characters. If identifiers are
> >1 character long, there are 63 possibilities. For 2-character
> >identifiers, there are 63*63 possibilities, and so on.
> >N-character identifiers have 63**N possibilities, where ** is
> >exponentiation ("to the power of").
>
> I am completely lost that somewhat long number consisted of 39 digits,
> so any module with more than 39 chars in it massively exceeds that
> number in potential values. More precisely 39 digit numbers are
> approximately 2^129 and a single char restricted to the digits, letters
> and _ can represent 2^6 so we need a string of roughly 22 chars.
So your answer is that it would take somewhere between 22 and 39
characters. Andy Sawyer came up with approximately 26 characters.
Let's be conservative and assume it's 22 characters.
> Now the real problem is that module names are NOT normally randomly
> selected.
Too true. Names longer than 2 or 3 characters are likely to be either
abbreviations or words, with a high occurrence of vowels and all the
other observations that make text so compressible.
Still, for the sake of discussion, assume that 22-character names
would be adequate.
> > John Nagle <nagle@animats.com> wrote
> > > Of course, we're in this mess because C++ lacks module
> > > names. Namespaces should have done the job, but they
> > > don't.
Can you give an example that demonstrates why namespaces don't solve
"this mess"?
> >Advanced guru question: Without bothering to compute the exact odds,
> >let's just take it as a given that the average module length will be
> >FAR less than this lofty goal. Instead, visit Hades and locate a
> >snowball, then come back and compute the odds of even 10 major players
> >(not counting compiler vendors, complaince testers, and magazine
> >reviewers) using a module length this long, for any reasonable
> >definition of the word "major".
This was really my point. If "module names" are to be as effective
as MD5 hash codes, they would have to be (on average) at least
22 characters long. I have actually seen a production C++ program
that had a 20-character identifier, and I cursed the programmer that
wrote it for forcing me to do so as well.
If we used module names, we would still (eventually) run into a
situation where we have two modules with the same name.
If MD5 is not workable, then module names would be even worse.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Thu, 7 Nov 2002 06:44:54 +0000 (UTC) Raw View
Allan W wrote:
>>>John Nagle <nagle@animats.com> wrote
>>>
>>>> Of course, we're in this mess because C++ lacks module
>>>>names. Namespaces should have done the job, but they
>>>>don't.
>>>>
>
> Can you give an example that demonstrates why namespaces don't solve
> "this mess"?
C++ doesn't have modules. There's
nothing at the start of a file which identifies it at the
language level, like module names in Modula or Ada. So
we don't have a way to talk about what part of a program
is defined in a file. There's no way to say "this file contains
the implementation of class foo", or "this file contains
the declaration of class foo". Guards are a hack to solve
part of that problem.
When "namespace" went in, this could have been addressed,
but it wasn't.
I realize it's hopeless to actually fix anything in this
language, though.
On a vaguely related note, I'd like to have the ability to
define locally visible private functions of a class within a
file that implements the class, without changing the class definition.
This would reduce the visiblity of implementation detail in header
files, encourage the addition of private class member functions rather
than the expansion of existing ones, and reduce recompilations.
It would, though, require that vtable generation be moved to link
time. But that would mean changing the linker.
The tradition that "you can't change the linker"
comes from the fact that the UNIX PDP-11 linker was written
in assembler and had almost no comments. (I had to fix
it once.) This is less of an issue today than it was in 1981.
Another advantage of link-time vtable generation is that you
don't pull in unused class member functions.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 7 Nov 2002 13:29:29 +0000 (UTC) Raw View
John Nagle wrote:
> Allan W wrote:
....
> The tradition that "you can't change the linker"
> comes from the fact that the UNIX PDP-11 linker was written
> in assembler and had almost no comments. (I had to fix
> it once.) This is less of an issue today than it was in 1981.
It's not so much that you can't change the linker, as that you
shouldn't. The linker ideally allows you to link together object code
compiled in many different languages. That means that it's a bad place
to implement language-specific features.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 7 Nov 2002 15:03:11 +0000 (UTC) Raw View
John Nagle wrote:
> C++ doesn't have modules. There's
> nothing at the start of a file which identifies it at the
> language level, like module names in Modula or Ada.
Ada does not define any relationship between packages
and files. It is completely up to the implementation
to document how it finds the specification and body
of a package which is needed by some piece of code.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 31 Oct 2002 16:12:14 CST Raw View
nagle@animats.com (John Nagle) wrote
> Perl doesn't need include guards, despite a roughly
> comparable textual inclusion mechanism. This should tell
> us something.
I think it tells us that Perl isn't the same as C++.
Is that what you were getting at?
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 31 Oct 2002 16:12:20 CST Raw View
andys@evo6.com.NoSpam (Andy Sawyer) wrote
> usenet cpp@lehrerfamily.com (Joshua Lehrer) wrote:
> > Do both:
>
> I concur with "Do both", but not with the method in which you do it:
>
> > #pragma once
> > #ifndef GUARD
> > #define GUARD
> > // code
> > #endif
> >
> > that way, the compiler can safely ignore the #pragma once if it
> > doesn't know what it is
>
> And the compiler can safely (for instance) delete the file if it knows
> that's what #pragma once means to that implementation.
>
> ,----[ 16.6 Pragma directive ]
> | 1 A preprocessing directive of the form
> |
> | # pragma pp-tokens(opt) new-line
> |
> | causes the implementation to behave in an implementation-defined
> | manner. Any pragma that is not recognized by the implementation
> | is ignored.
> `----
>
> Note the "implementation-defined" in there. And, since (AFAICS) the
> term "recognized" is not defined by the standard, an implementation
> can recognize all #pragmas for which it has no defined behaviour and
> define an alternate behaviour for that case (which may, for instance,
> include terminating compilation - as long as the behaviour is defined
> by the implementation). Several of the compilers I use issue warnings
> when they encouter a pragma that they don't "recognize".
Certainly it is possible for two different compilers to pick the same
name for their implementation-defined pragma. Perhaps one compiler
implements #pragma DiscardAfterUse to mean that objects allocated with
new() are automatically deleted at the end of their scope; and perhaps
another implements #pragma DiscardAfterUse to mean what you said (include
this header file, then delete it).
But "once"? Are you suggesting that there might be some compiler today
where #pragma once is equivalent to #pragma deleteme or even #error?
The standard doesn't require #pragma keywords to be in English, but
common sense says that it will at least make sense in some language.
Call it a QOI issue if you like, but if a compiler saw #pragma once
and assumed it was okay to delete it, I would call that the worst
compiler in history -- even if it was 100% compliant with the standard.
I'll change my mind if you can point to any spoken or scientific language,
dialect, subfield, etc. where a word spelled o-n-c-e means "delete when
through."
> (It could
> reasonably be argued that they actually do "recognize" the pragma, but
> don't understand it.)
Perhaps, to misquote a famous American president, it depends on what the
meaning of the word "is" is? No, I wouldn't call this "reasonable."
You'll have to explain to me how a compiler could "recognize" a pragma
that it doesn't understand, and how this justifies deleting source files
(or even files that MIGHT have source code in them) or any other non-temp
files that it didn't directly generate.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Thu, 31 Oct 2002 16:12:36 CST Raw View
After seeing the hacks piled upon hacks created to deal with
this problem, I'm beginning to think that it might be worth having
the compiler compute the MD5 of included files to determine if they're
duplicates. This is only necessary where the file system can't
resolve that question, but it would definitively answer the question
"is it a duplicate"?
Maybe we only do this for
using "filename";
It would be nice to do some cleanup here.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 31 Oct 2002 16:45:58 CST Raw View
andys@evo6.com.NoSpam (Andy Sawyer) wrote
> > > #ifndef Include guard nagle h 15805 38595 931000 02 ams
> allan w@my-dejanews.com (Allan W) wrote:
> > It looks like underscores got translated to spaces when you posted?
> ============ MODERATOR'S COMMENT:
> It's not his newsfeed. The underscores are already gone by the
> time the message enters the moderation queue.
> ============ END OF MODERATOR'S COMMENT
> They're fine in the post I sent, they're fine in the post as I read it
> from my news server. I'd suggest the problem is either your newsserver
> or newsreader.
Not to belabor the point -- since it's obvious what Andy meant --
but if it's not showing up at the point of moderation, how could
they come back on Andy's news server? Something strange is going on.
Do you see an underscore between these two arrows: ==> _ <== ?
> > In any case, this approach prevents a useful technique from being
> > employed.
>
> No, it doesn't.
I guess not, if the very long include-guard-name never changes. It
certainly makes it inconvenient, though.
> > Many shops advocate lifting the "include guard" logic into
> > the code that includes it. For instance:
> > #ifndef INCLUDE FOO H
That was INCLUDE_FOO_H. That was INCLUDE-FOO-H except with underscores
instead of dashes.
> > #include "foo.h"
> > #endif
>
> In my personal opinion, that's an insane way to code. Not only is it
> error-prone (I wouldn't like to count the number of times I've seen
> that style with a type in either including code or included code -
> best case scenario is that a file gets included twice, worst case is
> it doesn't get included at all), but it does little to enhance
> readability, but much to hide the intent of code.
It can't allow the file to be included twice, unless the included file
fails to define INCLUDE-FOO-H (with underscores) or spells it wrong.
(As I point out below, the include file should also use internal
include-guards -- so even if it was included twice, no harm done.)
I can't imagine a situation where the file wouldn't be included at all,
unless someone defined INCLUDE-FOO-H outside of foo.h. That programmer
ought to be shot anyway. Perhaps you're considering the case where
two different include files (in different paths) are both named foo.h?
But this is a bad idea anyway.
I don't get to make every policy decision personally. I dislike this
policy (though I'd stop short of calling it "insane"). I at least
sympathise with it's rationale, which I did explain:
> > ...where foo.h would probably include the same include-guard logic as
> > well. The point is compilers that don't understand the "include-guard
> > optimization." If the compiler has to open foo.h, parse the first
> > #if statement, scan for the corresponding #endif statement, and then
> > close the include file -- this could slow down compilation.
>
> So could writing comments.
Do you have any metrics to back this up? Perhaps a 6-line program with
32,000 lines of comment would compile more quickly if the comments
were removed. If the ratio is more reasonable (say, 3 comments per
source line), I doubt you would measurably improve performance by
removing the comments -- do you disagree?
By contrast, if you can avoid even opening the file, you can potentially
make a large difference (if the project is large enough). If your project
has 200 source files, and you reduce the average number of #includes
from 20 to 15, you've avoided 1,000 file opens. How long does it take on
your system to open and close a file 1,000 times, assuming that your
OS's file cache (if there is one) is flushed each time?
In this particular case, I managed to arrange a compromise: we used the
guards in BOTH places. If the #ifndef in the main program used
the wrong name, the one in the header file itself would still work --
and so the program would still compile correctly. If the one in the
main program WAS spelled right, the compile would go faster as well.
Win-win.
> > The same code wrapped around the #include statement itself should
> > prevent this. Using techniques like the one above -- or Microsoft's
> > UID in the include guard -- prevent this, because you would have to
> > change the #if code in the main file every time you change the
> > included file.
>
> No more so than any other mechanism - I don't change the include guard
> every time I change the file. The guard is generated when the file is
> created, not every time it's edited.
So the net effect is a very long include-guard name. I suppose this is
to reduce the chance of a collision with user code? (If some programmer
used a variable named INCLUDE-FOO-H (with underscores), I'd ask why in a
code review.) Or perhaps you're worried about two include files in
different paths with the same name?
My point, however, wasn't that using #ifndefs in the main program was
the preferred way to go -- just that some shops do it. Using long
automatically-generated names for the include guards might help to
reduce even further macro/code name collisions, but it also prevents
this technique from working properly.
> > Personally I've never liked this (in part because we had #pragma once
> > anyway), but that is the rule in some shops.
>
> And there are shops which have the "no warnings, ever" rule. In my
> opinion, they're about as valid as each other (which isn't very valid).
You're right, a lot of shops have this rule too. Unlike the first one,
I do like the no-warnings rule and fully support it. I could give you
a lot of reasons, but that's an entirely different subject -- and one
that has been explained far better than I could. Try a Google search
here or in comp.lang.c++.moderated.
> > > For production code, we have adopted the practice that all
> > > third-party headers - including standard library headers - are
> > > included via headers which have guards of the form described
> > > above. (for each standard library header, there's a header
> > > which looks something like:
> > >
> > > -- stdlib/list.hxx --
> > >
> > > #ifndef Include guard stdlib list hxx 1234 5678 90123 01 base
> > > #define Include guard stdlib list hxx 1234 5678 90123 01 base
> > > #include <list>
> > > #endif /* Include guard stdlib list hxx 1234 5678 90123 01 base */
> > <list> and most other standard headers already have their own
> > include-guards.
>
> I'm well aware of that. That's not the reason we do it. Tell me if the
> following program is well formed:
>
> #include <iostream>
>
> int main()
> {
> std::string s("Hello, world");
> std::cout << s << std::endl;
> return 0;
> }
>
> You don't know. But If you replace:
> #include <iostream>
> with:
> #include <stdlib/iostream.hxx>
> Then it is. (Assuming you have our iostream.hxx)
I'm sorry -- I think I missed this point entirely.
<stdlib/iostream.hxx> includes <iostream> -- why would one of
these programs always be well-formed while the other might not be?
> > > At least it's better than "#pragma once" - which basically
> > > suggests that the compiler take a wild guess.
> >
> > Oh, come on. Either the compiler understands #pragma once, or it
> > doesn't -- there's nothing "wild" about it.
>
> Oh come on, how does the compiler know if the file in question has
> previously been included?
Your point before (which was snipped) was that since the semantics of
#pragma aren't defined, #pragma once might do something entirely
unrelated to reducing the number of includes, such as deleting the
file when it was finished. That's why I used the phrase "Oh, come
on" -- I was incredulous at the idea.
> Any technique involving pathnames/filename
> are wild guesses, since with modern operating systems there are many
> ways to alias files and paths. It's entirely possible that:
>
> #include <nowhere/foo.h>
> #include <erewhon/bar.hxx>
>
> actually include the same file. There's no guarantee that there's any
> way for the compiler to be able to determine that other than by
> opening the files in question and reading them - and this is
> /especially/ true when the files in question are located remotely.
Agreed, this is a possibility. Nevertheless, #pragma once has been
used successfully in many compilers for many years.
Certainly there are SOME cases when the compiler has reason to believe
that two pathnames refer to the same file -- such as when the filenames
(including path) are identical, or (on some OS's) differ only by case.
Handling this case only, would be satisfactory. If something in the new
standard implements "#pragma once" semantics, I'd be satisfied if it
said something like
When two different names refer to the same source file, it is
undefined whether a second #include directive processes that file.
Then, if the compiler DOES know that the two files are the same, it has
the right to ignore the second one -- but if it doesn't know or can't
be sure, then it has the right to process the second one.
You might want to point out that two identical filenames might refer
to different files -- for instance, two #includes that both refer to a
card reader might read different contents. I suspect that most people
reading source code through a card reader would copy it to a random-
access media first; therefore, if a non-file device has source code
with #pragma once (or whatever), I'm satisfied to let this be undefined
behavior as well.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Andy Sawyer <andys@evo6.com.NoSpam>
Date: Fri, 1 Nov 2002 02:56:21 CST Raw View
In article <3DC0AC66.1040206@animats.com>,
on Thu, 31 Oct 2002 16:12:36 CST,
John Nagle <nagle@animats.com> wrote:
> After seeing the hacks piled upon hacks created to deal with
> this problem, I'm beginning to think that it might be worth having
> the compiler compute the MD5 of included files to determine if they're
> duplicates.
Of course, if the platform doesn't provide a mechanism for determining
of two paths lead to the same file, calculating an MD5 hash relies on
reading the whole file, so those that object to include guards
won't. It also relies on the hash being unique for different files,
which, of course, cannot be gaurenteed.
> This is only necessary where the file system can't
> resolve that question, but it would definitively answer the question
> "is it a duplicate"?
Clearly not. If the file system can't resolve that question, the only
way to ensure that it isn't a duplicate is to compare the files. And
even that may not be sufficient - since it's possible (although
unusual ) for two textually identical headers to themselves #include
_different_ headers). (Indeed, the "two textually identical headers"
could actually be the /same/ header accessed via multiple paths)
> Maybe we only do this for
>
> using "filename";
>
> It would be nice to do some cleanup here.
Providing language support (above include guards) to prevent multiple
inclusion probably has some merit, but I still argue that the header
file should be the one to name itself from that standpoint. As I
sugeested elsewhere, it might be reasonable for a header to "publish"
an identifier which is used to determine whether it has been
previously included or not. For example:
#provides "Acme, Inc. Road Runner traps"
Semantically, this is roughly similar to the "#pragma once" idea but,
importantly, places control of the identification in the hands of the
programmer rather than a compiler which may not have any useful way of
identifying the fact that two files are, in fact, the same file.
Regards,
Andy S.
Footnotes:
That is to say, it's unusual for anyone to take the steps required
for this to happen - although yes, I have seen it done.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Andy Sawyer <andys@evo6.com.NoSpam>
Date: Fri, 1 Nov 2002 11:25:35 CST Raw View
In article <7f2735a5.0210301400.2e612df6@posting.google.com>,
on Thu, 31 Oct 2002 16:12:20 CST,
allan_w@my-dejanews.com (Allan W) wrote:
> andys@evo6.com.NoSpam (Andy Sawyer) wrote
> > usenet cpp@lehrerfamily.com (Joshua Lehrer) wrote:
> > > Do both:
> >
> > I concur with "Do both", but not with the method in which you do it:
> >
> > > #pragma once
> > > #ifndef GUARD
> > > #define GUARD
> > > // code
> > > #endif
> > >
> > > that way, the compiler can safely ignore the #pragma once if it
> > > doesn't know what it is
> >
> > And the compiler can safely (for instance) delete the file if it knows
> > that's what #pragma once means to that implementation.
> >
> > ,----[ 16.6 Pragma directive ]
> > | 1 A preprocessing directive of the form
> > |
> > | # pragma pp-tokens(opt) new-line
> > |
> > | causes the implementation to behave in an implementation-defined
> > | manner. Any pragma that is not recognized by the implementation
> > | is ignored.
> > `----
> >
> > Note the "implementation-defined" in there. And, since (AFAICS) the
> > term "recognized" is not defined by the standard, an implementation
> > can recognize all #pragmas for which it has no defined behaviour and
> > define an alternate behaviour for that case (which may, for instance,
> > include terminating compilation - as long as the behaviour is defined
> > by the implementation). Several of the compilers I use issue warnings
> > when they encouter a pragma that they don't "recognize".
>
> Certainly it is possible for two different compilers to pick the same
> name for their implementation-defined pragma. Perhaps one compiler
> implements #pragma DiscardAfterUse to mean that objects allocated with
> new() are automatically deleted at the end of their scope; and perhaps
> another implements #pragma DiscardAfterUse to mean what you said (include
> this header file, then delete it).
>
> But "once"? Are you suggesting that there might be some compiler today
> where #pragma once is equivalent to #pragma deleteme or even #error?
No, I'm not suggesting that #pragma once is "equivalent to"
anything. What I wrote was:
"And the compiler can safely (for instance) delete the file if it knows
that's what #pragma once means to that implementation."
So am I "suggesting" (your word) anything? No. I'm making a statement
- a statment based on a careful reading of the standard - that there
_might_ (your word) be such a compiler, and furthur that it could even
be a conforming implementation.
On the other hand, the answer to the question I beleive you intended
to ask is No. I'm not saying (or even suggesting) that there _is_ such
an implementation.
> The standard doesn't require #pragma keywords to be in English, but
> common sense says that it will at least make sense in some language.
#pragma once:
"Include a header file precisely once, then delete it to ensure it
cannot be included a second time".
Yes, it's an unlikely case. But don't tell me it's not possible -
mankind has done some pretty bizarre things in its time, and
unexpectedly deleting files would not be amongst the worst offence by
quite some distance.
> Call it a QOI issue if you like, but if a compiler saw #pragma once
> and assumed it was okay to delete it, I would call that the worst
> compiler in history
You'd be entitled to your viewpoint. But of course, if it /didn't/ do
what the documentation said, you'd probably get upset to.
> -- even if it was 100% compliant with the standard.
If it was 100% conforming, I'd probably make sure that I avoided the
use of #pragma once, and also ensure that I had adequate facilites to
ensure I could recover from the compiler deleting files as it saw fit.
> I'll change my mind if you can point to any spoken or scientific
> language, dialect, subfield, etc. where a word spelled o-n-c-e means
> "delete when through."
OK, there's read "once" quantum cryptography. Last time I looked, it
was largely theoretical - but the theory is pretty sound. Basically,
you can only "read" the ciphertext once, since reading it changes the
state ("deletes the ciphertext"). Ahis has the nice side-effect that
you can tell if anybody else has read your encoded message.
Then there's read "once" computer memory - a notable example being
the volatile store on the AGC - which is core storeage which loses
("deletes") its value when read (so if you want to keep the value, you
need to write it back immediatly after reading it).
There's two examples. Not only that, they're examples of _exactly_
what you seem to think "#pragma once" should means - read this _one
time only_.
Presumably you've either changed your mind, or
you've reneged on your promise to do so?
> > (It could reasonably be argued that they actually do "recognize"
> > the pragma, but don't understand it.)
>
> Perhaps, to misquote a famous American president, it depends on what the
> meaning of the word "is" is?
Why? I didn't use the word "is" in the above scentene.
> No, I wouldn't call this "reasonable."
Recognition and understanding are distinct - but recognition is
normally necessary for understanding. I _recognize_ the sound of my
next door neighbours' dogs barking, but I don't _understand_ it. Would
you call that reasonable? (You may be Dr Doolittle and undestand dog,
but I don't.) I _recognize_ the sound of spoken Thai, but don't
_understand_ it (except "ling" means "monkey" and "chang" means
"elephant" - don't ask :-). Would you call that reasonable? I
_recognise_ the fact that Keanu Reeves is a movie star, but I
certainly don't _understand_ it. Can you explain that?
> You'll have to explain to me how a compiler could "recognize" a
> pragma that it doesn't understand
That's pretty fundamental to the pre-processor grammer. If a line is
of the form:
(whitespace)*#(whitespace)*pragma
Then what follows is a pragma. That's _very_ easily recognized by even
the most primitive of parsers. (If a compiler _doesn't_ recognize this
as a pragma, how can it figure out whether it understands it or not?)
> and how this justifies deleting source files (or even files that
> MIGHT have source code in them) or any other non-temp files that it
> didn't directly generate.
Go and read the standard - if the implementation defines the behaviour
in that way, then that behaviour is justifed. I'm not for an instant
suggesting it's particularly good behaviour, but it's certainly
/possible/.
Of course, if your argument is (as it seems to be) that a compiler
can't "recognize" a #pragma it doesn't "understand", then do please
tell me which compiler implements #pragma once the way you want, and
behaves in a conforming fashion wrt "unrecognized" pragmas?
Note that your entire attack (since that's what it is) is based on
the fact that I deliberatly chose an extreme example of what
implementation defined behaviour (in the form of a #pragma) might
mean. There are many, many other things that it might mean "start
telling a fairy story" (as in "Once upon a time,"), for instance. Or
"start a game of #nethack "). Or stop compilation. My point was that
using a "naked" #pragma once is asking for trouble.
I also notice that you've (repeatedly) chosen to ignore the fact that
"#pragma once" in and of itself doesn't provide enough information for
the compiler to tell if a file has been previously included or not.
Regards,
Andy S.
Footnotes:
IIRC, there was a C compiler which did precisely this when it hit a
certain pragma. (Although that may well be urban legend)
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Fri, 1 Nov 2002 13:40:10 CST Raw View
Andy Sawyer wrote:
> In article <3DC0AC66.1040206@animats.com>,
> on Thu, 31 Oct 2002 16:12:36 CST,
> John Nagle <nagle@animats.com> wrote:
>
>
>> After seeing the hacks piled upon hacks created to deal with
>>this problem, I'm beginning to think that it might be worth having
>>the compiler compute the MD5 of included files to determine if they're
>>duplicates.
>>
>
> Of course, if the platform doesn't provide a mechanism for determining
> of two paths lead to the same file, calculating an MD5 hash relies on
> reading the whole file, so those that object to include guards
> won't.
The only case in which you have to reread a file is when
two files appear to have different names, but are in fact the
same because of filename issues.
In fact, since that's probably an error, it could be made
an error to include two textually identical copies of the
same file under different names, with MD5 used to check this.
That's probably worth implementing as a warning, and might
expose some problems in build systems.
> It also relies on the hash being unique for different files,
> which, of course, cannot be gaurenteed.(sic)
The odds are rather good.
See http://www.karenware.com/newsletters/2002/2002-07-12.asp
for the odds calculation.
There are are 340,282,366,920,938,463,463,374,607,431,768,211,455
possible MD5 hash values. And files distribute uniformly over
the keyspace; it's a cryptographic-grade hash that's survived
examination in the crypto community. People use MD5 values
to decide whether to back up files.
Of course, we're in this mess because C++ lacks module
names. Namespaces should have done the job, but they
don't.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 1 Nov 2002 15:55:16 CST Raw View
John Nagle <nagle@animats.com> wrote in message news:<3DC0AC66.1040206@animats.com>...
> After seeing the hacks piled upon hacks created to deal with
> this problem, I'm beginning to think that it might be worth having
> the compiler compute the MD5 of included files to determine if they're
> duplicates. This is only necessary where the file system can't
> resolve that question, but it would definitively answer the question
> "is it a duplicate"?
>
> Maybe we only do this for
>
> using "filename";
>
> It would be nice to do some cleanup here.
Interesting idea, but it would require OS support.
In order to compute the MD5 hash of a file without OS support, the
compiler would have to scan the entire file. But if it has to scan
the entire file, it might as well just process it as it does today
(with suitable #ifndef / #endif directives). It should take about
the same amount of time.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 1 Nov 2002 16:13:11 CST Raw View
> >> usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
> >> >#pragma once
> >> >#ifndef GUARD
> >> >#define GUARD
> >> >// code
> >> >#endif
> >
> >fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> >> Actually putting the #pragma there may defeat the usual #ifndef guard
> >> optimization. If you really want to do this, better put it inside the
> >> #ifndef:
> >>
> >> #ifndef GUARD
> >> #define GUARD
> >> #pragma once
> >> // code
> >> #endif
> allan_w@my-dejanews.com (Allan W) writes:
> >Seems to me that if the #pragma takes effect, GUARD will still have
> >been defined once (and the #ifndef will never be tested). On the
> >other hand, if the #pragma is ignored, then GUARD will still
> >function normally.
> >
> >Please explain the difference.
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> Some compilers do the optimization of checking for include guards and
> only reading the file once if it has an include guard. Such compilers
> might fail to recognize the #ifndef in the first example as an include
> guard, since the #ifndef doesn't occur at the start of the file, and so
> might fail to apply the optimization. The result would be unnecessarily
> slow compilation on such compilers.
I guess that makes sense. Previously I had thought only about how
#pragma once can be used or ignored -- I never thought about the
include-guard optimization.
It's a shame, though. If compilers recognize #pragma once, then the
first version works just fine. If compilers do not recognize #pragma once,
at least they ought to realize the fact that they don't recognize it,
which (in the case of #pragma) means that it must be ignored. If those
compilers treated unrecognized #pragmas like comments, then the second
form would work for them too.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 1 Nov 2002 22:12:38 CST Raw View
In comp.std.c++, John Nagle <nagle@animats.com> writes:
>Andy Sawyer wrote:
>
>> It also relies on the hash being unique for different files,
>> which, of course, cannot be gaurenteed.(sic)
>
> The odds are rather good.
>
>See http://www.karenware.com/newsletters/2002/2002-07-12.asp
>for the odds calculation.
The statistical conlusions reached on that page are severely flawed.
Apparently the author is unaware of the statistical phenomenon known
as "The Birthday Paradox".
The page posits a hypothetical situation in which 1.9e24 files files
have been created, and asks what is the chance that there is an MD5
hash collision between two of those files. The author quotes some
misleading numbers
| 1 in 1,797,000,000,000,000 of the possible MD5 hash values have been
| used. Put another way, the number of MD5 hashes we've computed is less
| that 0.00000000000006% of the total available.
and then concludes
| It's possible, in theory, that two of those hash values will be the
| same. But as you can see from the numbers, it's very unlikely. The odds
| are better that everyone on earth will be hit by lightning, on the same
| day -- the day you win the Irish Sweepstakes.
However, this conclusion is wrong.
Note that the author does *not* calculate the chance of there being two
hash values which collide, but instead merely *asserts* that "it's very
unlikely". This statement is false. By my calculations, the chance of
that two or more of the hash values in the situation described will be
the same is greater than 99.9999%.
The number of different random files that you need to create in order
to expect at least one collision is only 2^64, i.e. 1.8e19, which is
much less than 1.9e24.
However, that said, MD5 should be sufficient for most practical purposes
in the short to medium-term. But the kind of hyperbole and invalid
statistical analysis in the cited article certainly doesn't help
the case for MD5.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Andy Sawyer <andys@evo6.com.NoSpam>
Date: Sun, 3 Nov 2002 00:09:39 CST Raw View
In article <7f2735a5.0211011334.daf9ec7@posting.google.com>,
on Fri, 1 Nov 2002 16:13:11 CST,
allan_w@my-dejanews.com (Allan W) wrote:
> > >> usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
> > >> >#pragma once
> > >> >#ifndef GUARD
> > >> >#define GUARD
> > >> >// code
> > >> >#endif
> > >
> > >fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> > >> Actually putting the #pragma there may defeat the usual #ifndef guard
> > >> optimization. If you really want to do this, better put it inside the
> > >> #ifndef:
> > >>
> > >> #ifndef GUARD
> > >> #define GUARD
> > >> #pragma once
> > >> // code
> > >> #endif
>
> > allan_w@my-dejanews.com (Allan W) writes:
> > >Seems to me that if the #pragma takes effect, GUARD will still have
> > >been defined once (and the #ifndef will never be tested). On the
> > >other hand, if the #pragma is ignored, then GUARD will still
> > >function normally.
> > >
> > >Please explain the difference.
>
> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> > Some compilers do the optimization of checking for include guards and
> > only reading the file once if it has an include guard. Such compilers
> > might fail to recognize the #ifndef in the first example as an include
> > guard, since the #ifndef doesn't occur at the start of the file, and so
> > might fail to apply the optimization. The result would be unnecessarily
> > slow compilation on such compilers.
>
> I guess that makes sense. Previously I had thought only about how
> #pragma once can be used or ignored -- I never thought about the
> include-guard optimization.
You might also want to think about how #pragma once can be
/implemented/.
> It's a shame, though. If compilers recognize #pragma once, then the
> first version works just fine.
If a preprocessor implements #pragma once in a fashion which saves it
from opening the file for the second (and subsequent) inclusion -
which is, I believe, your contention - then either form should work
fine for that preprocessor. (In fact, in such an implementation, the
#pragma could be anywhere in the file).
> If compilers do not recognize #pragma once, at least they ought to
> realize the fact that they don't recognize it, which (in the case of
> #pragma) means that it must be ignored.
Many compilers don't, in fact, "ignore" unrecognized pragmas - they
emit warnings upon encountering them, which doesn't (in my book) count
as "ignoring".
> If those compilers treated unrecognized #pragmas like comments, then
> the second form would work for them too.
As Fergus said:
,----
| Such compilers might fail to recognize the #ifndef in the first
| example as an include guard, since the #ifndef doesn't occur at the
| start of the file, and so might fail to apply the optimization.
`----
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Sun, 3 Nov 2002 17:37:42 +0000 (UTC) Raw View
In article <7f2735a5.0210311159.510f1b0d@posting.google.com>,
on Thu, 31 Oct 2002 16:45:58 CST,
allan_w@my-dejanews.com (Allan W) wrote:
> andys@evo6.com.NoSpam (Andy Sawyer) wrote
> > > > #ifndef Include guard nagle h 15805 38595 931000 02 ams
>
> > allan w@my-dejanews.com (Allan W) wrote:
> > > It looks like underscores got translated to spaces when you posted?
>
> > ============ MODERATOR'S COMMENT:
> > It's not his newsfeed. The underscores are already gone by the
> > time the message enters the moderation queue.
> > ============ END OF MODERATOR'S COMMENT
>
> > They're fine in the post I sent, they're fine in the post as I
> > read it from my news server. I'd suggest the problem is either
> > your newsserver or newsreader.
>
> Not to belabor the point -- since it's obvious what Andy meant --
> but if it's not showing up at the point of moderation, how could
> they come back on Andy's news server? Something strange is going on.
In the first message (the one Allan objected to), the underscores were
present in the posting I received. In the post containing the
moderator's comment, they were not.
> Do you see an underscore between these two arrows: ==> _ <== ?
Yes.
> That was INCLUDE_FOO_H. That was INCLUDE-FOO-H except with underscores
> instead of dashes.
So much for not belaboring (sic) the point.
> It can't allow the file to be included twice, unless the included file
> fails to define INCLUDE-FOO-H (with underscores) or spells it wrong.
Of if some other file erroneously spells it's own include guard wrong.
> (As I point out below, the include file should also use internal
> include-guards -- so even if it was included twice, no harm done.)
I thought the whole point of external guards was that including the
same file twice _was_ considered harmful?
> I can't imagine a situation where the file wouldn't be included at all,
> unless someone defined INCLUDE-FOO-H outside of foo.h. That programmer
> ought to be shot anyway. Perhaps you're considering the case where
> two different include files (in different paths) are both named foo.h?
> But this is a bad idea anyway.
Not necessarily.
> > > ...where foo.h would probably include the same include-guard logic as
> > > well. The point is compilers that don't understand the "include-guard
> > > optimization." If the compiler has to open foo.h, parse the first
> > > #if statement, scan for the corresponding #endif statement, and then
> > > close the include file -- this could slow down compilation.
> >
> > So could writing comments.
>
> Do you have any metrics to back this up?
Processing comments has to consume time, since they have to be read to
be ignored. If you can demonstrate a way to process comments in
_exactly_ zero time, then I'll change my mind. (As an aside, I recall
once reading that C compilers spent as much as 50% of their parse time
ignoring whitespace - which included comments - but I can't give you a
citation for that statistic, so feel free to ignore it.)
> Perhaps a 6-line program with 32,000 lines of comment would compile
> more quickly if the comments were removed. If the ratio is more
> reasonable (say, 3 comments per source line), I doubt you would
> measurably improve performance by removing the comments -- do you
> disagree?
I didn't say is was "measurable", I said it _could_ slow down
compilation. If you're going to try to refute what I write, then
please refute what I write.
> By contrast, if you can avoid even opening the file, you can potentially
> make a large difference (if the project is large enough).
"can", "potentially", "if". How vague can you make your comment?
> If your project has 200 source files, and you reduce the average
> number of #includes from 20 to 15, you've avoided 1,000 file
> opens. How long does it take on your system to open and close a file
> 1,000 times, assuming that your OS's file cache (if there is one) is
> flushed each time?
I don't know. How long does it take on your system? I have, in
response to another of your posts, posted numbers about various
include models, based on my system.
Again, I'll point out that increased compilation time is not "dead time"
(since you can use that time for other activities), whilst adding
external include guards is dead time, since you can't use if for
anything else.
> So the net effect is a very long include-guard name. I suppose this is
> to reduce the chance of a collision with user code? (If some programmer
> used a variable named INCLUDE-FOO-H (with underscores), I'd ask why in a
> code review.) Or perhaps you're worried about two include files in
> different paths with the same name?
The latter. I have exactly zero control over the filenames or include
gaurds used by some third party library vendors.
> My point, however, wasn't that using #ifndefs in the main program was
> the preferred way to go -- just that some shops do it. Using long
> automatically-generated names for the include guards might help to
> reduce even further macro/code name collisions, but it also prevents
> this technique from working properly.
That's not the first time that you've made the claim that it "prevents
the technique from working properly", but you've yet to demonstrate
that to be the case.
> You're right, a lot of shops have this rule too. Unlike the first one,
> I do like the no-warnings rule and fully support it.
Yet again, I'll point out that there are certain development
environments in which using that rule prevents the use of the STL. (Or
by "no warnings" do you mean "no warnings except the ones I turn off
because they're inconvenient?")
> > I'm well aware of that. That's not the reason we do it. Tell me if the
> > following program is well formed:
> >
> > #include <iostream>
> >
> > int main()
> > {
> > std::string s("Hello, world");
> > std::cout << s << std::endl;
> > return 0;
> > }
> >
> > You don't know. But If you replace:
> > #include <iostream>
> > with:
> > #include <stdlib/iostream.hxx>
> > Then it is. (Assuming you have our iostream.hxx)
>
> I'm sorry -- I think I missed this point entirely.
> <stdlib/iostream.hxx> includes <iostream> -- why would one of
> these programs always be well-formed while the other might not be?
<stdlib/iostream.hxx> does indeed include <iostream>. You chose to
make the (unfounded and incorrect) assumtion that it doesn't do
anything else. I've said before that the reasons for doing this were
partly to do with portability and maintenance. <stdlib/iostream.hxx>
also takes steps to ensure that std::basic_string is defined (The
mechanism in fact varies depending on the target platform) - because
it's a very common assumption made by programmers with little
experience of multi-platform development. The point is that the extra
level of indirection gives a single point of customisation for each
header (be they standard library or third party).
> > > > At least it's better than "#pragma once" - which basically
> > > > suggests that the compiler take a wild guess.
> > >
> > > Oh, come on. Either the compiler understands #pragma once, or it
> > > doesn't -- there's nothing "wild" about it.
> >
> > Oh come on, how does the compiler know if the file in question has
> > previously been included?
>
> Your point before (which was snipped) was that since the semantics of
> #pragma aren't defined, #pragma once might do something entirely
> unrelated to reducing the number of includes, such as deleting the
> file when it was finished. That's why I used the phrase "Oh, come
> on" -- I was incredulous at the idea.
My point was that "#pragma once" has _no way_ of knowing for sure that
a given file has been included without opening it. Which is why I
wrote what follows. Do you actually read posts before you start
attacking them? Or do you just start at the top and work down?
> > Any technique involving pathnames/filename
> > are wild guesses, since with modern operating systems there are many
> > ways to alias files and paths. It's entirely possible that:
> >
> > #include <nowhere/foo.h>
> > #include <erewhon/bar.hxx>
> >
> > actually include the same file. There's no guarantee that there's any
> > way for the compiler to be able to determine that other than by
> > opening the files in question and reading them - and this is
> > /especially/ true when the files in question are located remotely.
>
> Agreed, this is a possibility.
In other words, #pragma once suggests that the compiler take a wild
guess. Which you found "incredulous".
> Certainly there are SOME cases when the compiler has reason to believe
> that two pathnames refer to the same file -- such as when the filenames
> (including path) are identical, or (on some OS's) differ only by case.
> Handling this case only, would be satisfactory. If something in the new
> standard implements "#pragma once" semantics, I'd be satisfied if it
> said something like
> When two different names refer to the same source file, it is
> undefined whether a second #include directive processes that
> file.
I'm pretty sure you don't mean that. I really don't think you want to
introduce more "undefined" behaviour to the preprocessor, do you?
> Then, if the compiler DOES know that the two files are the same, it has
> the right to ignore the second one -- but if it doesn't know or can't
> be sure, then it has the right to process the second one.
If the compiler knows that including the second file will not change
the semantics of the program it _currently_ has the "right" to ignore
the second one. If "it doesn't know, or can't be sure", then it has
the "right" to process the file. This is normally referred to as the
"as if" rule.
> You might want to point out that two identical filenames might refer
> to different files
Please define (in terms which are meaningful in the standard), what
"identical filenames" means. It's quite possible that two files
included into the same translation unit might have lines which read:
#include "foo.h"
And refer to different headers. Even if those headers reside on
random-access media.
> -- for instance, two #includes that both refer to a
> card reader might read different contents.
They might. But I doubt many people are reading C++ source form card
readers. I'll defer to your expertise in that matter.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Sun, 3 Nov 2002 22:17:27 +0000 (UTC) Raw View
On Sun, 3 Nov 2002 17:37:42 +0000 (UTC), andys@evo6.com.NoSpam (Andy Sawyer) wrote:
>In article <7f2735a5.0210311159.510f1b0d@posting.google.com>,
> on Thu, 31 Oct 2002 16:45:58 CST,
> allan_w@my-dejanews.com (Allan W) wrote:
>> (As I point out below, the include file should also use internal
>> include-guards -- so even if it was included twice, no harm done.)
>
>I thought the whole point of external guards was that including the
>same file twice _was_ considered harmful?
Degrees: incorrect versus not optimal.
- Alf
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: Mon, 28 Oct 2002 18:10:25 +0000 (UTC) Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<apcsel$677$1@mulga.cs.mu.OZ.AU>...
> nagle@animats.com (John Nagle) writes:
>
> >> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> >>>What if the same file is read through different paths?
> >
> > Perhaps the compilation takes longer. This isn't
> >a real problem.
>
> Many header files will result in compilation errors if they are
> included twice (and not protected with an #ifndef ... #define ...
> #endif guard), e.g. because they define enumeration types.
> So it's not just compilation time -- it affects whether or not the
> program will compile.
>
which is exactly my point. Do both:
#pragma once
#ifndef GUARD
#define GUARD
// code
#endif
that way, the compiler can safely ignore the #pragma once if it
doesn't know what it is, and will continue to work, as before. And,
rather than writing complicated logic to detect that this header file
is guarded by the define "GUARD", the compiler vendor could implement
"#pragma once".
The point is that the detection logical is complicated- it is very
difficult to parse a header and know that it is guarded by a #define.
Rather than forcing vendors to implement this complicated mechanism,
why not give them a hint with "#pragma once"
joshua lehrer
factset research systems
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Mon, 28 Oct 2002 18:26:22 +0000 (UTC) Raw View
Andy Sawyer wrote:
> Which is exactly the reason they should have include guards.
Of course, that assumes the symbol name used in the
include guard is unique. In practice, it's usually the
name of the file, without namespace or path information.
Thus, include guards establish a module
naming convention. Not a very good one, but a convention.
Note that the effect is that if you include two versions
of the same file, you get only the first one. Is this
a bug or a feature?
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Mon, 28 Oct 2002 18:32:15 +0000 (UTC) Raw View
Fergus Henderson wrote:
> nagle@animats.com (John Nagle) writes:
>
>
>>>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>>>
>>>>What if the same file is read through different paths?
>>>>
>> Perhaps the compilation takes longer. This isn't
>>a real problem.
>>
>
> Many header files will result in compilation errors if they are
> included twice ... because they define enumeration types.
I hadn't thought of that. Is it a bug or a feature that
you can't define the same enum type twice, identically, without
an error? Almost everything else you usually include tolerates
duplicate declarations as long as they're identical.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Tue, 29 Oct 2002 01:13:42 +0000 (UTC) Raw View
In article <3DBAE188.6090506@animats.com>,
on Mon, 28 Oct 2002 18:32:15 +0000 (UTC),
nagle@animats.com (John Nagle) wrote:
> Fergus Henderson wrote:
>
> > nagle@animats.com (John Nagle) writes:
> >
>
> >>>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> >>>
> >>>>What if the same file is read through different paths?
> >>>>
> >> Perhaps the compilation takes longer. This isn't
> >>a real problem.
> >>
> > Many header files will result in compilation errors if they are
>
> > included twice ... because they define enumeration types.
>
>
> I hadn't thought of that. Is it a bug or a feature that
> you can't define the same enum type twice, identically, without
> an error?
It's a feature.
> Almost everything else you usually include tolerates duplicate
> declarations as long as they're identical.
That's because declarations and definitions are not the same
thing.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Tue, 29 Oct 2002 01:13:49 +0000 (UTC) Raw View
In article <3DBC1DA2.5050302@animats.com>,
on Mon, 28 Oct 2002 18:26:22 +0000 (UTC),
nagle@animats.com (John Nagle) wrote:
> Andy Sawyer wrote:
>=20
> > Which is exactly the reason they should have include guards.
>=20
> Of course, that assumes the symbol name used in the
> include guard is unique. In practice, it's usually the
> name of the file, without namespace or path information.
Speak for yourself. My include guards (for a just-created header named
"nagle.h") look something like:
#ifndef Include_guard_nagle_h_15805_38595_931000_02_ams
They're added automatically for me by my editor (and, for those that
care, "nagle_h" is obviously generated from the file name, the first 3
groups of digits are generated based on the time & date, the last
group of digits is dependant on the number of new guards generated
during the current editor session=B9, and "ams" are my initials.
For production code, we have adopted the practice that all
third-party=B2 headers - including standard library headers - are
included via headers which have guards of the form described
above. (for each standard library header, there's a header which looks
something like:
-- stdlib/list.hxx --
#ifndef Include_guard_stdlib_list_hxx_1234_5678_90123_01_base
#define Include_guard_stdlib_list_hxx_1234_5678_90123_01_base
#include <list>
#endif /* Include_guard_stdlib_list_hxx_1234_5678_90123_01_base */
And anywhere I need to use <list> (including in another header), I'd
write:
#include <stdlib/list.hxx>
It might be a tiny bit of overhead, but has paid dividends in terms of
portabiliy and maintainance. (Remember, you can fix almost anything
with an extra level of indirection :-)
> Thus, include guards establish a module naming convention.
A naming convention, yes. I'm not convinced that "module" belongs in
there, though.
> Not a very good one, but a convention.
At least it's better than "#pragma once" - which basically suggests
that the compiler take a wild guess.
> Note that the effect is that if you include two versions
> of the same file, you get only the first one. Is this
> a bug or a feature?
Yes :-)
Regards,
Andy S.
Footnotes:=20
=B9 Just in case someone attempts to generate several headers in the
space of 1 second :-)
=B2 Since it includes standard library headers, maybe that's "second
party" too...
--=20
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 29 Oct 2002 20:32:03 +0000 (UTC) Raw View
nagle@animats.com (John Nagle) wrote:
> Fergus Henderson wrote:
>
> > nagle@animats.com (John Nagle) writes:
> >
>
> >>>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> >>>
> >>>>What if the same file is read through different paths?
> >>>>
> >> Perhaps the compilation takes longer. This isn't
> >>a real problem.
> >>
> > Many header files will result in compilation errors if they are
>
> > included twice ... because they define enumeration types.
>
>
> I hadn't thought of that. Is it a bug or a feature that
> you can't define the same enum type twice, identically, without
> an error?
Actually you can -- it's just that the two definitions need to be
in different translation units.
> Almost everything else you usually include tolerates duplicate
> declarations as long as they're identical.
The same error on multiple definitions within a single translation unit
also applies for definitions of classes, inline functions, templates,
and static constants -- indeed just about everything other than
typedefs, it seems. Of course multiple *declarations* are fine,
but C++ is fairly consistent about forbidding multiple *definitions*
within a single translation unit, apart from the exception of typedefs.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 29 Oct 2002 20:32:11 +0000 (UTC) Raw View
usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<apcsel$677$1@mulga.cs.mu.OZ.AU>...
>> nagle@animats.com (John Nagle) writes:
>>
>> >> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>> >>>What if the same file is read through different paths?
>> >
>> > Perhaps the compilation takes longer. This isn't
>> >a real problem.
>>
>> Many header files will result in compilation errors if they are
>> included twice (and not protected with an #ifndef ... #define ...
>> #endif guard), e.g. because they define enumeration types.
>> So it's not just compilation time -- it affects whether or not the
>> program will compile.
>
>which is exactly my point. Do both:
>
>#pragma once
>#ifndef GUARD
>#define GUARD
>// code
>#endif
>that way, the compiler can safely ignore the #pragma once if it
>doesn't know what it is, and will continue to work, as before.
Actually putting the #pragma there may defeat the usual #ifndef guard
optimization. If you really want to do this, better put it inside the
#ifndef:
#ifndef GUARD
#define GUARD
#pragma once
// code
#endif
But IMHO it's a easier for a few compiler vendors to implement the #ifndef
guard optimization than for hundreds of thousands of C++ programmers to add
"#pragma once" to all their header files. Furthermore, implementing the
#ifndef guard optimization can be done now, whereas using "#pragma once"
now would result in annoying warning messages about unrecognized pragmas
from many compilers, and switching these warnings off would then have
the drawback that real spelling errors in pragmas would go undetected.
>And, rather than writing complicated logic to detect that this header file
>is guarded by the define "GUARD", the compiler vendor could implement
>"#pragma once".
The header guard check logic is really not that complicated, especially
in comparison to all the other things that a compiler implementor
has to deal with. It's only about 50 lines of code or thereabouts.
Implementing #pragma once would be about as much work, since new pragmas
need to be documented.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 29 Oct 2002 20:32:13 +0000 (UTC) Raw View
nagle@animats.com (John Nagle) wrote in message
news:<3DBAE188.6090506@animats.com>...
> Fergus Henderson wrote:
> > nagle@animats.com (John Nagle) writes:
> >>>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> >>>>What if the same file is read through different paths?
> >> Perhaps the compilation takes longer. This isn't
> >>a real problem.
> > Many header files will result in compilation errors if they are
> > included twice ... because they define enumeration types.
> I hadn't thought of that. Is it a bug or a feature that you can't
> define the same enum type twice, identically, without an error?
> Almost everything else you usually include tolerates duplicate
> declarations as long as they're identical.
Are you sure of that? Almost all of my header files define classes, and
you can't define a class twice in the same translation unit.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Wed, 30 Oct 2002 10:17:36 +0000 (UTC) Raw View
In article <31c49f0d.0210261515.56afb0a@posting.google.com>,
on Mon, 28 Oct 2002 18:10:25 +0000 (UTC),
usenet_cpp@lehrerfamily.com (Joshua Lehrer) wrote:
> Do both:
I concur with "Do both", but not with the method in which you do it:
> #pragma once
> #ifndef GUARD
> #define GUARD
> // code
> #endif
>=20
> that way, the compiler can safely ignore the #pragma once if it
> doesn't know what it is
And the compiler can safely (for instance) delete the file if it knows
that's what #pragma once means to that implementation.
,----[ 16.6 Pragma directive ]
| 1 A preprocessing directive of the form
|
| # pragma pp-tokens(opt) new-line
|=20
| causes the implementation to behave in an implementation-defined
| manner. Any pragma that is not recognized by the implementation
| is ignored.
`----
Note the "implementation-defined" in there. And, since (AFAICS) the
term "recognized" is not defined by the standard, an implementation
can recognize all #pragmas for which it has no defined behaviour and
define an alternate behaviour for that case (which may, for instance,
include terminating compilation - as long as the behaviour is defined
by the implementation). Several of the compilers I use issue warnings
when they encouter a pragma that they don't "recognize". (It could
reasonably be argued that they actually do "recognize" the pragma, but
don't understand it.)
The correct way is to write:
#if defined( USE_PRAGMA_ONCE )
#pragma once
#endif
#ifndef GUARD
#define GUARD
// code
#endif
Where you have defined "USE_PRAGMA_ONCE" elsewhere for compilers which
implement the semantics you desire. Of course, "#pragma once" becomes
less appearling when you have to jump through those hoops (as you may
well find you have to do it your code needs to be ported to another
compiler.)
> The point is that the detection logical is complicated- it is very
> difficult to parse a header and know that it is guarded by a #define.=20
> Rather than forcing vendors to implement this complicated mechanism,
> why not give them a hint with "#pragma once"
As a hint, "#pragma once" (or similar) may be useful to the
implementation, but it can't (in itself) eliminate the need for
include guards. As has been pointed out elsewhere, the same included
file could be reached through several "paths", and there may not be
way to determine if the two (or more) of those paths refer to the same
file.
(What follows is an off-the-top-of-my-head idea, and hence hasn't been
thoroughly thought through=B9, so please feel free to rip it to shreds :-=
)
You could play with the #pragma once syntax a bit, perhaps and
implement something like:
#pragma provide "identifier"
(where "identifier" is a user-defined string which 'identifies' the
included file's contents (e.g. #pragma provides "vendor standard library
algorithms", provides "mycompany magic functions" etc.)
The the implementation could then ignore include files which "provide" a
facility which has already been "provided".
Regards,
Andy S.
Footnotes:=20
=B9 Try spelling /that/ nine times quickly :-)
--=20
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 30 Oct 2002 18:46:17 +0000 (UTC) Raw View
Andy Sawyer wrote:
> In article <31c49f0d.0210261515.56afb0a@posting.google.com>,
> on Mon, 28 Oct 2002 18:10:25 +0000 (UTC),
> usenet_cpp@lehrerfamily.com (Joshua Lehrer) wrote:
>
>
>>Do both:
Perl doesn't need include guards, despite a roughly
comparable textual inclusion mechanism. This should tell
us something.
John Nagle
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 30 Oct 2002 20:27:43 +0000 (UTC) Raw View
James Kanze wrote:
> nagle@animats.com (John Nagle) wrote in message
> news:<3DBAE188.6090506@animats.com>...
>
>>Fergus Henderson wrote:
>>
>
>>>nagle@animats.com (John Nagle) writes:
>>>
>
>>>>>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>>>>>
>
>>>>>>What if the same file is read through different paths?
>>>>>>
>
>>>> Perhaps the compilation takes longer. This isn't
>>>>a real problem.
>>>>
>
>>>Many header files will result in compilation errors if they are
>>>included twice ... because they define enumeration types.
>>>
>
>> I hadn't thought of that. Is it a bug or a feature that you can't
>>define the same enum type twice, identically, without an error?
>>Almost everything else you usually include tolerates duplicate
>>declarations as long as they're identical.
>>
>
> Are you sure of that? Almost all of my header files define classes, and
> you can't define a class twice in the same translation unit.
You're right.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 30 Oct 2002 20:27:50 +0000 (UTC) Raw View
andys@evo6.com.NoSpam (Andy Sawyer) wrote
> My include guards (for a just-created header named
> "nagle.h") look something like:
>
> #ifndef Include guard nagle h 15805 38595 931000 02 ams
>
> They're added automatically for me by my editor (and, for those that
> care, "nagle h" is obviously generated from the file name, the first 3
> groups of digits are generated based on the time & date, the last
> group of digits is dependant on the number of new guards generated
> during the current editor session , and "ams" are my initials.
It looks like underscores got translated to spaces when you posted?
Otherwise this isn't valid, is it?
In any case, this approach prevents a useful technique from being
employed. Many shops advocate lifting the "include guard" logic into
the code that includes it. For instance:
#ifndef INCLUDE_FOO_H
#include "foo.h"
#endif
...where foo.h would probably include the same include-guard logic as
well. The point is compilers that don't understand the "include-guard
optimization." If the compiler has to open foo.h, parse the first
#if statement, scan for the corresponding #endif statement, and then
close the include file -- this could slow down compilation. The same
code wrapped around the #include statement itself should prevent this.
Using techniques like the one above -- or Microsoft's UID in the
include guard -- prevent this, because you would have to change the
#if code in the main file every time you change the included file.
Personally I've never liked this (in part because we had #pragma once
anyway), but that is the rule in some shops.
> For production code, we have adopted the practice that all
> third-party headers - including standard library headers - are
> included via headers which have guards of the form described
> above. (for each standard library header, there's a header which looks
> something like:
>
> -- stdlib/list.hxx --
>
> #ifndef Include guard stdlib list hxx 1234 5678 90123 01 base
> #define Include guard stdlib list hxx 1234 5678 90123 01 base
> #include <list>
> #endif /* Include guard stdlib list hxx 1234 5678 90123 01 base */
>
> And anywhere I need to use <list> (including in another header), I'd
> write:
>
> #include <stdlib/list.hxx>
>
>
> It might be a tiny bit of overhead, but has paid dividends in terms of
> portabiliy and maintainance. (Remember, you can fix almost anything
> with an extra level of indirection :-)
17.4.2.1/2 A translation unit may include library headers in any order
(clause 2). Each may be included more than once, where no effect
different from being included exactly once [except for <cassert> and
<assert.h> when NDEBUG changes]
In other words, <list> and most other standard headers already has their
own include-guards.
> At least it's better than "#pragma once" - which basically suggests
> that the compiler take a wild guess.
Oh, come on. Either the compiler understands #pragma once, or it
doesn't -- there's nothing "wild" about it.
> > Note that the effect is that if you include two versions
> > of the same file, you get only the first one. Is this
> > a bug or a feature?
>
> Yes :-)
It's a feature. If you didn't want it, you wouldn't use #pragma once.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 30 Oct 2002 22:06:26 +0000 (UTC) Raw View
> usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
> >which is exactly my point. Do both:
> >
> >#pragma once
> >#ifndef GUARD
> >#define GUARD
> >// code
> >#endif
>
> >that way, the compiler can safely ignore the #pragma once if it
> >doesn't know what it is, and will continue to work, as before.
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> Actually putting the #pragma there may defeat the usual #ifndef guard
> optimization. If you really want to do this, better put it inside the
> #ifndef:
>
> #ifndef GUARD
> #define GUARD
> #pragma once
> // code
> #endif
Seems to me that if the #pragma takes effect, GUARD will still have
been defined once (and the #ifndef will never be tested). On the
other hand, if the #pragma is ignored, then GUARD will still
function normally.
Please explain the difference.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Thu, 31 Oct 2002 01:32:27 +0000 (UTC) Raw View
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D MODERATOR'S COMMENT:=20
It's not his newsfeed. The underscores are already gone by the
time the message enters the moderation queue.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D END OF MODERATOR'S COMMENT
In article <7f2735a5.0210291050.683a7af6@posting.google.com>,
on Wed, 30 Oct 2002 20:27:50 +0000 (UTC),
allan_w@my-dejanews.com (Allan W) wrote:
> andys@evo6.com.NoSpam (Andy Sawyer) wrote
> > My include guards (for a just-created header named
> > "nagle.h") look something like:
> >=20
> > #ifndef Include guard nagle h 15805 38595 931000 02 ams
> >=20
> > They're added automatically for me by my editor (and, for those that
> > care, "nagle h" is obviously generated from the file name, the first =
3
> > groups of digits are generated based on the time & date, the last
> > group of digits is dependant on the number of new guards generated
> > during the current editor session , and "ams" are my initials.
>=20
> It looks like underscores got translated to spaces when you posted?
They're fine in the post I sent, they're fine in the post as I read it
from my news server. I'd suggest the problem is either your newsserver
or newsreader.
> Otherwise this isn't valid, is it?
It's perfectly vald as I wrote it.
> In any case, this approach prevents a useful technique from being
> employed.
No, it doesn't.
> Many shops advocate lifting the "include guard" logic into
> the code that includes it. For instance:
> #ifndef INCLUDE_FOO_H
> #include "foo.h"
> #endif
>=20
In my personal opinion, that's an insane way to code. Not only is it
error-prone (I wouldn't like to count the number of times I've seen
that style with a type in either including code or included code -
best case scenario is that a file gets included twice, worst case is
it doesn't get included at all), but it does little to enhance
readability, but much to hide the intent of code.
> ...where foo.h would probably include the same include-guard logic as
> well. The point is compilers that don't understand the "include-guard
> optimization." If the compiler has to open foo.h, parse the first
> #if statement, scan for the corresponding #endif statement, and then
> close the include file -- this could slow down compilation.
So could writing comments.
> The same code wrapped around the #include statement itself should
> prevent this. Using techniques like the one above -- or Microsoft's
> UID in the include guard -- prevent this, because you would have to
> change the #if code in the main file every time you change the
> included file.
No more so than any other mechanism - I don't change the include guard
every time I change the file. The guard is generated when the file is
created, not every time it's edited.
> Personally I've never liked this (in part because we had #pragma once
> anyway), but that is the rule in some shops.
And there are shops which have the "no warnings, ever" rule. In my
opinion, they're about as valid as each other (which isn't very valid).
> > For production code, we have adopted the practice that all
> > third-party headers - including standard library headers - are
> > included via headers which have guards of the form described
> > above. (for each standard library header, there's a header which look=
s
> > something like:
> >=20
> > -- stdlib/list.hxx --
> >=20
> > #ifndef Include guard stdlib list hxx 1234 5678 90123 01 base
> > #define Include guard stdlib list hxx 1234 5678 90123 01 base
> > #include <list>
> > #endif /* Include guard stdlib list hxx 1234 5678 90123 01 base */
Your newsfeed is stripping underscores again.
> 17.4.2.1/2 A translation unit may include library headers in any orde=
r
> (clause 2). Each may be included more than once, where no effect
> different from being included exactly once [except for <cassert> and
> <assert.h> when NDEBUG changes]
>
> In other words, <list> and most other standard headers already has thei=
r
> own include-guards.
I'm well aware of that. That's not the reason we do it. Tell me if the
following program is well formed:
#include <iostream>
int main()
{
std::string s("Hello, world");
std::cout << s << std::endl;
return 0;
}
You don't know. But If you replace:
#include <iostream>
with:
#include <stdlib/iostream.hxx>
Then it is. (Assuming you have our iostream.hxx)
> > At least it's better than "#pragma once" - which basically
> > suggests that the compiler take a wild guess.
>=20
> Oh, come on. Either the compiler understands #pragma once, or it
> doesn't -- there's nothing "wild" about it.
Oh come on, how does the compiler know if the file in question has
previously been included? Any technique involving pathnames/filename
are wild guesses, since with modern operating systems there are many
ways to alias files and paths. It's entirely possible=B9 that:
#include <nowhere/foo.h>
#include <erewhon/bar.hxx>
Actually include the same file. There's no guarantee that there's any
way for the compiler to be able to determine that other than by
opening the files in question and reading them - and this is
/especially/ true when the files in question are located remotely.
Regards,
Andy S.
Footnotes:=20
=B9 Yes, it's unlikely, but it _is_ possible.
--=20
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Thu, 31 Oct 2002 03:28:31 +0000 (UTC) Raw View
On Thu, 31 Oct 2002 01:32:27 +0000 (UTC), andys@evo6.com.NoSpam (Andy Sawyer) wrote:
>In article <7f2735a5.0210291050.683a7af6@posting.google.com>,
> on Wed, 30 Oct 2002 20:27:50 +0000 (UTC),
> allan_w@my-dejanews.com (Allan W) wrote:
>
>> Many shops advocate lifting the "include guard" logic into
>> the code that includes it. For instance:
>> #ifndef INCLUDE_FOO_H
>> #include "foo.h"
>> #endif
>>
>
>In my personal opinion, that's an insane way to code. Not only is it
>error-prone (I wouldn't like to count the number of times I've seen
>that style with a type in either including code or included code -
>best case scenario is that a file gets included twice, worst case is
>it doesn't get included at all), but it does little to enhance
>readability, but much to hide the intent of code.
This technique can significantly reduce compile time when the include
file is large and/or resides on network storage. So it's not at all
an "insane" technique. It's a pragmatic trade-off.
It's true it's error-prone. But normally any error in spelling the
include guard symbol correctly is benign. The only effect of such an
error is no optimization for this particular include of the file.
And even this can be guarded for in the following way in the included
file:
#ifdef INCLUDE_FOO_H_GARBLE_GARBLE_GUID_GARBLE
# ifndef MULTIPLE_INCLUDES_ALLOWED
# error [somepath/foo.h] included twice
# endif
#else
# define INCLUDE_FOO_H_GARBLE_GARBLE_GUID_GARBLE
... contents of foo.h ...
#endif // INCLUDE_FOO_H_GARBLE_GARBLE_GUID_GARBLE
With this one can choose to disallow non-optimized includes, or
not, as one's preferences and viewpoints on sanity dictate.
For those who choose to not define MULTIPLE_INCLUDES_ALLOWED there
is a practical problem of finding the offending including file --
but that job can possibly be automated via a script.
- Alf
PS: Last time this was discussed, some years ago, many people argued
that the #error was in error. But that assumes a contract other than
the one the include file actually has. Perhaps that misunderstanding
can be avoided this time around (more people now familiar with Lakos).
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Thu, 31 Oct 2002 11:51:37 +0000 (UTC) Raw View
In article <3dc096ac.397026562@news.bluecom.no>,
alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach) wrote:
> On Thu, 31 Oct 2002 01:32:27 +0000 (UTC), andys@evo6.com.NoSpam
> (Andy Sawyer) wrote:
>=20
> >In article <7f2735a5.0210291050.683a7af6@posting.google.com>,
> > on Wed, 30 Oct 2002 20:27:50 +0000 (UTC),
> > allan_w@my-dejanews.com (Allan W) wrote:
> >
> >> Many shops advocate lifting the "include guard" logic into
> >> the code that includes it. For instance:
> >> #ifndef INCLUDE_FOO_H
> >> #include "foo.h"
> >> #endif
> >>
> >
> >In my personal opinion, that's an insane way to code. Not only is it
> >error-prone (I wouldn't like to count the number of times I've seen
> >that style with a type in either including code or included code -
> >best case scenario is that a file gets included twice, worst case is
> >it doesn't get included at all), but it does little to enhance
> >readability, but much to hide the intent of code.
>=20
> This technique can significantly reduce compile time when the include
> file is large and/or resides on network storage. So it's not at all
> an "insane" technique. It's a pragmatic trade-off.
It's only pargamatic when the amount of time it saves outstrips the
amount of time it costs. Also note that the extra time it costs (three
lines of code for every include, "I've included foo.h so how come this
doesn't work"? [see below]) ties up both the development enviroment
_and_ the developer. The (compilation) time that is "saves" ties up only =
the
development environment - the developer can use that time in many
ways, e.g. make the coffee, write documentation, read email, post to
c.s.c++, talk to your co-workers etc. If your compilations happen
quick enough that you can't do any of those, you don't need to worry
about it this much).
> It's true it's error-prone.
Which, in itself, is motive enough to many to suggest "don't do
it". Especially when there's a less error-prone alternative
(i.e. don't do it)
> But normally any error in spelling the include guard symbol
> correctly is benign. The only effect of such an error is no
> optimization for this particular include of the file.
That depends on where it's spelt incorrectly. If it's spelt
incorrectly /inside/ an included file, then another file might /not/
be included:
#ifndef INCLUDED_FOO_H
#include "foo.h"
#endif
#ifndef INCLUDED_FOOL_H
#include "fool.h"
#endif
If foo.h mistakely #defined INCLUDED_FOOL_H (instead of
INCLUDED_FOO_H), then fool.h won't be included.
Given only the six lines of code above (and the fact that I've
pointed out the answer), it'd be easy to find and fix. But given a
real world example, with potentially many, nested, headers=B9 - and no
indication as to _why_ some entitiy which is declared in fool.h can't
be referenced - that would be hard work to find. Especially since
everything works fine in a translation unit which doesn't include
foo.h, or perhaps includes it later than fool.h (This is yet another
part of the reason that our include guards are long and contain of
strings of [apparently] arbitrary digits - it considerably reduces the
liklihood of a mis-spelt guard clashing with another file).
Of course, you could save yourself a lot of effort by taking another
leaf from my (metaphorical) book: each "real" file (such as your
"foo.h") could have a "wrapper" file, which contains the guards and
the #include. The "wrapper" is three(ish) lines long, and just gets
included:
----------- Begin wrapper_foo.h
#ifndef INCLUDE_FOO_H_YadaYadaYada
#include "foo.h"
#endif
----------- End
No more, no less. (If you want to put a revision log in there, you can
:-). Since, in principle, these files need to only be written once,
and should thereafter only change rarely (if at all), there should be
no resistance=B2 to developers having local copies (even if "foo.h" is
at the other end of a slow connection)
Then in your code you can write:
#include "wrapper_foo.h"
#include "wrapper_bar.h"
Which is, to me, both easier to write _and_ to read. (Effectively,
you're swapping "ifdef some stuff that changes every time" for
"wrapper_" (or however you choose to distinguish your files) - which
has the important benefit of being the same bit of text for every
include file. Sure, there's an extra file open/read/close
involved. But (as I've pointed out) that really ought to be a local
file, that won't be too much of an issue.
So you get all of the alleged advantages of the "external" include
guard model, and none of the real disadvantages.
Apart from which, in my experience template instantiation and link
time _far_ outstrips header processing on all but the most trivial
programs, so most of this is actually pretty academic. (Of course,
it's rare that I recompile an entire, large, program. Due to the
wonderful innovations of timestamps and makefiles, I can usually get
away with recompiling what's changed, and since I normally try and
keep any given source file below maybe a thousand lines, that doesn't
normally take very long. Yes, I normally do a full rebuild before
system testing, but that isn't something that happens every day)
Regards,
Andy S.
Footnotes:=20
=B9 i.e. the number and depth of which might begin to justify this level
of obfuscation in the search for better compilation times
=B2 Even from the most pointy-haired of bosses!
--=20
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Thu, 31 Oct 2002 19:45:41 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) writes:
>> usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
>> >#pragma once
>> >#ifndef GUARD
>> >#define GUARD
>> >// code
>> >#endif
>
>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>> Actually putting the #pragma there may defeat the usual #ifndef guard
>> optimization. If you really want to do this, better put it inside the
>> #ifndef:
>>
>> #ifndef GUARD
>> #define GUARD
>> #pragma once
>> // code
>> #endif
>
>Seems to me that if the #pragma takes effect, GUARD will still have
>been defined once (and the #ifndef will never be tested). On the
>other hand, if the #pragma is ignored, then GUARD will still
>function normally.
>
>Please explain the difference.
Some compilers do the optimization of checking for include guards and
only reading the file once if it has an include guard. Such compilers
might fail to recognize the #ifndef in the first example as an include
guard, since the #ifndef doesn't occur at the start of the file, and so
might fail to apply the optimization. The result would be unnecessarily
slow compilation on such compilers.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach)
Date: Thu, 31 Oct 2002 19:45:48 +0000 (UTC) Raw View
On Thu, 31 Oct 2002 11:51:37 +0000 (UTC), andys@evo6.com.NoSpam (Andy Sawyer) wrote:
>In article <3dc096ac.397026562@news.bluecom.no>,
> alf_p_steinbach@yahoo.no.invalid (Alf P. Steinbach) wrote:
>
>> [about external include guard] ... normally any error in spelling
>> the include guard symbol correctly is benign. The only effect of
>> such an error is no optimization for this particular include of the file.
>
>That depends on where it's spelt incorrectly. If it's spelt
>incorrectly /inside/ an included file, then another file might /not/
>be included:
>
>#ifndef INCLUDED_FOO_H
>#include "foo.h"
>#endif
>#ifndef INCLUDED_FOOL_H
>#include "fool.h"
>#endif
>
>
>If foo.h mistakely #defined INCLUDED_FOOL_H (instead of
>INCLUDED_FOO_H), then fool.h won't be included.
This is trivially true.
And it is true also for the situation where you don't use an external
include guard, relying only on the internal guard.
So, it is irrelevant wrt. use of an external include guard -- if it's
"insane", as you put it, then an internal guard is just as "insane", and
I think it will be very hard to convince the C++ community of that... ;-)
(
Furthermore, the interaction can't happen when the include guard symbol
is GUID-based, as it was in the snipped example.
Not that GUID-based include guards solve a pressing problem, IMHO.
I've only found them useful for examples in Usenet discussions, to
avoid fruitless side-tracks like the above -- but even that doesn't
always work, since it's so easy to snip the actual example.
)
> Of course, you could save yourself a lot of effort by taking another
>leaf from my (metaphorical) book: each "real" file (such as your
>"foo.h") could have a "wrapper" file, which contains the guards and
>the #include. The "wrapper" is three(ish) lines long, and just gets
>included:
>
>----------- Begin wrapper_foo.h
>#ifndef INCLUDE_FOO_H_YadaYadaYada
>#include "foo.h"
>#endif
>----------- End
I like this technique and have employed it on occasion. Not for
reasons of efficiency, but because with some compilers, a few #pragmas
(and on occasion, #defines) are required to avoid warnings, to adjust
the set of declarations/definitions brought in by the include, or even to
get typesafe declarations. For standard lib headers and others.
Using a wrapper headerfile the external include guard, if employed,
would/should be placed in the wrapper, as shown in your example.
>So you get all of the alleged advantages of the "external" include
>guard model, and none of the real disadvantages.
I take this to mean that you don't consider your own point about
include guard interaction to be a real disadvantage; if so, then we
agree on that, at least.
However, the include optimization that external include guards
offer isn't there unless the wrapper itself uses a guarded include,
as your own example does, so I think that in spite of your comment
that external include guards are "insane" you actually use them.
Whether this calls for some language addition is another matter; as
I've argued elsewhere (and most people seem to agree with except they
think we're past the point where it could be introduced) what we need
is not more fine-tuning of the include mechanism but *module* support.
>... [snipped]
- Alf
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 31 Oct 2002 20:58:16 +0000 (UTC) Raw View
> > > allan w@my-dejanews.com (Allan W) wrote:
> > >> Many shops advocate lifting the "include guard" logic into
> > >> the code that includes it. For instance:
> > >> #ifndef INCLUDE FOO H
> > >> #include "foo.h"
> > >> #endif
> > andys@evo6.com.NoSpam (Andy Sawyer) wrote:
> > >In my personal opinion, that's an insane way to code. Not only is it
> > >error-prone (I wouldn't like to count the number of times I've seen
> > >that style with a type in either including code or included code -
> > >best case scenario is that a file gets included twice, worst case is
> > >it doesn't get included at all), but it does little to enhance
> > >readability, but much to hide the intent of code.
> alf p steinbach@yahoo.no.invalid (Alf P. Steinbach) wrote:
> > This technique can significantly reduce compile time when the include
> > file is large and/or resides on network storage. So it's not at all
> > an "insane" technique. It's a pragmatic trade-off.
andys@evo6.com.NoSpam (Andy Sawyer) wrote
> It's only pargamatic when the amount of time it saves outstrips the
> amount of time it costs. Also note that the extra time it costs (three
> lines of code for every include, "I've included foo.h so how come this
> doesn't work"? [see below]) ties up both the development enviroment
> and the developer. The (compilation) time that is "saves" ties up only
> the development environment - the developer can use that time in many
> ways, e.g. make the coffee, write documentation, read email, post to
> c.s.c++, talk to your co-workers etc. If your compilations happen
> quick enough that you can't do any of those, you don't need to worry
> about it this much).
I worked on a BIG C++ project, back in the days when a Pentium-300 with
16Meg of RAM was considered very fast. That's the machine we used for
our weekly build of the entire project: IIRC, it was around 500 *.cpp
files and maybe 200 *.h files (NOT including the vendor- or
third-party libraries) built into six executables. I don't know the
average number of include files used in a cpp file, but I suspect it
was at least 10.
With the "old way," compiles had to be started Friday after work.
Someone would have to drive in late Saturday morning to make sure that
all went well, or to fix any minor errors that came up. If the weekend
person couldn't fix it, it became the first priority Monday morning --
and we didn't have a build that week.
We went through what has been described as "header file hell". A lot
of our main programs relied on one header file including another, which
meant that we could not remove that dependancy. Then finally we changed
policy to say that if you use a FOO object, you must include FOO.H,
even if some other include file has already included it. At the same
time, we used the "external-include-guard" shown above (but also, as
I've mentioned, with internal include guards). This required 50 mandays
of modifications -- we examined the #include files of every single source
module in the project. We considered this "experiment" a phenomenal
success, and well worth the investment in time. The new #include rules
became a permanent part of the company policy.
After that, we found that we could start that same compile Wednesday at
lunch. One person would sit and watch it while everyone else took a
lunch break -- and if an error came up, we could try again before
everyone went home for the day. The same header files were used by the
same cpp files. I attribute the difference in build time exclusively to
the use of external include-guards.
> > It's true it's error-prone.
>
> Which, in itself, is motive enough to many to suggest "don't do
> it". Especially when there's a less error-prone alternative
> (i.e. don't do it)
>
> > But normally any error in spelling the include guard symbol
> > correctly is benign. The only effect of such an error is no
> > optimization for this particular include of the file.
>
> That depends on where it's spelt incorrectly. If it's spelt
> incorrectly /inside/ an included file, then another file might /not/
> be included:
>
> #ifndef INCLUDED FOO H
> #include "foo.h"
> #endif
> #ifndef INCLUDED FOOL H
> #include "fool.h"
> #endif
>
> If foo.h mistakely #defined INCLUDED FOOL H (instead of
> INCLUDED FOO H), then fool.h won't be included.
An interesting point. But is this any different than accidentally
spelling "main" wrong?
> Given only the six lines of code above (and the fact that I've
> pointed out the answer), it'd be easy to find and fix. But given a
> real world example, with potentially many, nested, headers - and no
> indication as to why some entitiy which is declared in fool.h can't
> be referenced - that would be hard work to find. Especially since
> everything works fine in a translation unit which doesn't include
> foo.h, or perhaps includes it later than fool.h (This is yet another
> part of the reason that our include guards are long and contain of
> strings of [apparently] arbitrary digits - it considerably reduces the
> liklihood of a mis-spelt guard clashing with another file).
program.cpp (54) "showfool" undefined.
program.cpp (59) "fool" undefined.
program.cpp (104) pointer to unrecognized type "fool"
I think an experienced programmer would conclude fairly quickly that
fool.h wasn't being included for some reason. Debugging the problem
shouldn't take too long -- you can confirm the cause and locate the
problem at the same time, by adding
#ifdef INCLUDED-FOOL-H // (but use underscores, not hyphens)
#error INCLUDED-FOOL-H defined in XXX-H
#endif
after every #include that might have caused the problem.
> Of course, you could save yourself a lot of effort by taking another
> leaf from my (metaphorical) book: each "real" file (such as your
> "foo.h") could have a "wrapper" file, which contains the guards and
> the #include. The "wrapper" is three(ish) lines long, and just gets
> included:
>
> ----------- Begin wrapper foo.h
> #ifndef INCLUDE FOO H YadaYadaYada
> #include "foo.h"
> #endif
> ----------- End
>
> No more, no less. (If you want to put a revision log in there, you can
> :-).
I think you're also going to want a #define in there -- otherwise the
whole point of the #ifndef is lost.
> Since, in principle, these files need to only be written once,
> and should thereafter only change rarely (if at all), there should be
> no resistance to developers having local copies (even if "foo.h" is
> at the other end of a slow connection)
>
> Then in your code you can write:
>
> #include "wrapper foo.h"
> #include "wrapper bar.h"
>
> Which is, to me, both easier to write and to read. (Effectively,
> you're swapping "ifdef some stuff that changes every time" for
> "wrapper " (or however you choose to distinguish your files) - which
> has the important benefit of being the same bit of text for every
> include file. Sure, there's an extra file open/read/close
> involved. But (as I've pointed out) that really ought to be a local
> file, that won't be too much of an issue.
>
> So you get all of the alleged advantages of the "external" include
> guard model, and none of the real disadvantages.
Okay, I didn't really get the point of the 3-line version before.
(At first you said something about program correctness, which confused
me.) If I understand correctly, your point is to do the same thing as
the external guards, but in a new header file. The reason that you
don't state (but imply) is that #including this 3-line version many
times shouldn't significantly affect compile speeds, and it will only
include the "real" header once.
The correctness of this assumption depends on how long it takes to open
and close a local file on your system. Perhaps you could test this?
Add #include "emptyfile.h" 40 or 50 times to some project, and see if
it makes any difference on compile times.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 5 Nov 2002 00:44:25 +0000 (UTC) Raw View
Andy Sawyer <andys@evo6.com.NoSpam> wrote
> allan_w@my-dejanews.com (Allan W) wrote:
>
> > andys@evo6.com.NoSpam (Andy Sawyer) wrote
> > > And the compiler can safely (for instance) delete the file if it knows
> > > that's what #pragma once means to that implementation.
> > > Note the "implementation-defined" in there. And, since (AFAICS) the
> > > term "recognized" is not defined by the standard, an implementation
> > > can recognize all #pragmas for which it has no defined behaviour and
> > > define an alternate behaviour for that case (which may, for instance,
> > > include terminating compilation - as long as the behaviour is defined
> > > by the implementation). Several of the compilers I use issue warnings
> > > when they encouter a pragma that they don't "recognize".
> >
> > Certainly it is possible for two different compilers to pick the same
> > name for their implementation-defined pragma. Perhaps one compiler
> > implements #pragma DiscardAfterUse to mean that objects allocated with
> > new() are automatically deleted at the end of their scope; and perhaps
> > another implements #pragma DiscardAfterUse to mean what you said (include
> > this header file, then delete it).
> >
> > But "once"? Are you suggesting that there might be some compiler today
> > where #pragma once is equivalent to #pragma deleteme or even #error?
>
> No, I'm not suggesting that #pragma once is "equivalent to"
> anything. What I wrote was:
>
> "And the compiler can safely (for instance) delete the file if it knows
> that's what #pragma once means to that implementation."
> #pragma once:
> "Include a header file precisely once, then delete it to ensure it
> cannot be included a second time".
>
> Yes, it's an unlikely case. But don't tell me it's not possible -
> mankind has done some pretty bizarre things in its time, and
> unexpectedly deleting files would not be amongst the worst offence by
> quite some distance.
>
> > Call it a QOI issue if you like, but if a compiler saw #pragma once
> > and assumed it was okay to delete it, I would call that the worst
> > compiler in history
> > I'll change my mind if you can point to any spoken or scientific
> > language, dialect, subfield, etc. where a word spelled o-n-c-e means
> > "delete when through."
>
> OK, there's read "once" quantum cryptography. Last time I looked, it
> was largely theoretical - but the theory is pretty sound. Basically,
> you can only "read" the ciphertext once, since reading it changes the
> state ("deletes the ciphertext"). Ahis has the nice side-effect that
> you can tell if anybody else has read your encoded message.
>
> Then there's read "once" computer memory - a notable example being
> the volatile store on the AGC - which is core storeage which loses
> ("deletes") its value when read (so if you want to keep the value, you
> need to write it back immediatly after reading it).
>
> There's two examples. Not only that, they're examples of _exactly_
> what you seem to think "#pragma once" should means - read this _one
> time only_.
>
> Presumably you've either changed your mind, or
> you've reneged on your promise to do so?
Absolutely. I'm totally convinced. You betcha.
> > Perhaps, to misquote a famous American president, it depends on what the
> > meaning of the word "is" is?
>
> Why? I didn't use the word "is" in the above scentene.
My point was that even if semantic "wiggling" such as the ones in
your scentene makes points in high school debate clubs, it usually
doesn't carry much weight in business.
> Go and read the standard - if the implementation defines the behaviour
> in that way, then that behaviour is justifed. I'm not for an instant
> suggesting it's particularly good behaviour, but it's certainly
> /possible/.
My point was that it would be unreasonable for the implementation to
define it that way in the first place.
If I ever find a compiler that deletes files based on trivial
provocation such as
#pragma once
or even
x = ++x;
then I will keep my promise not to call it "the worst compiler in
history." However, I won't be using it either.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 5 Nov 2002 18:53:56 +0000 (UTC) Raw View
andys@evo6.com.NoSpam (Andy Sawyer) wrote in message
news:<iszjb5ii.fsf@ender.evo6.com>...
> In article <3dc096ac.397026562@news.bluecom.no>,
> alf p steinbach@yahoo.no.invalid (Alf P. Steinbach) wrote:
> > On Thu, 31 Oct 2002 01:32:27 +0000 (UTC), andys@evo6.com.NoSpam
> > (Andy Sawyer) wrote:
> > >In article <7f2735a5.0210291050.683a7af6@posting.google.com>,
> > > on Wed, 30 Oct 2002 20:27:50 +0000 (UTC),
> > > allan w@my-dejanews.com (Allan W) wrote:
> > >> Many shops advocate lifting the "include guard" logic into
> > >> the code that includes it. For instance:
> > >> #ifndef INCLUDE FOO H
> > >> #include "foo.h"
> > >> #endif
> > >In my personal opinion, that's an insane way to code. Not only is
> > >it error-prone (I wouldn't like to count the number of times I've
> > >seen that style with a type in either including code or included
> > >code - best case scenario is that a file gets included twice, worst
> > >case is it doesn't get included at all), but it does little to
> > >enhance readability, but much to hide the intent of code.
> > This technique can significantly reduce compile time when the
> > include file is large and/or resides on network storage. So it's
> > not at all an "insane" technique. It's a pragmatic trade-off.
> It's only pargamatic when the amount of time it saves outstrips the
> amount of time it costs.
Quite. I only use it on very large projects. But I've seen it change
the time required for a complete build from over a day to less than four
hours. On one project, using it allowed us to do a complete build of
all versions (four: two targets, each with and without Purify) every
week-end. Before using it, we had to start the build for a single
version around noon Friday to be sure that it was finished Monday
morning.
Today, of course, we'd just use g++, and avoid the hassle.
> Also note that the extra time it costs (three lines of code for every
> include, "I've included foo.h so how come this doesn't work"? [see
> below]) ties up both the development enviroment and the developer.
Every time I've seen it used, someone wrote an emacs command to insert
the works in one go. The same way we use emacs templates to ensure that
the include guards are there (and conform to the programming guidelines)
when you open a new .hh.
[...]
> Apart from which, in my experience template instantiation and link
> time far outstrips header processing on all but the most trivial
> programs, so most of this is actually pretty academic. (Of course,
> it's rare that I recompile an entire, large, program. Due to the
> wonderful innovations of timestamps and makefiles, I can usually get
> away with recompiling what's changed, and since I normally try and
> keep any given source file below maybe a thousand lines, that doesn't
> normally take very long. Yes, I normally do a full rebuild before
> system testing, but that isn't something that happens every day)
On one large project, we found it useful to do a complete rebuild every
week-end, with the integration team running regression tests on it. In
this way, any regression errors which didn't show up in unit tests are
detected when the changes are still fresh in mind.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 5 Nov 2002 20:02:45 +0000 (UTC) Raw View
John Nagle <nagle@animats.com> wrote
> Andy Sawyer wrote:
> > [MD5] also relies on the hash being unique for different files,
> > which, of course, cannot be gaurenteed.(sic)
>
> The odds are rather good.
>
> See http://www.karenware.com/newsletters/2002/2002-07-12.asp
> for the odds calculation.
>
> There are are 340,282,366,920,938,463,463,374,607,431,768,211,455
> possible MD5 hash values. And files distribute uniformly over
> the keyspace; it's a cryptographic-grade hash that's survived
> examination in the crypto community. People use MD5 values
> to decide whether to back up files.
Gosh what a website! I'm so excited to find it! Gosh!
I might even send some of my non-technical friends there -- but this
is clearly written for laymen. Programmers can probably find the same
information written much more concisely.
Not that I'm actually disagreeing with Karen. My first instinct was
to use expletives, when I saw this near the top of her article:
MD5... can compress any amount of data into a short sequence of
just 16 bytes! Think of it ... every book ever published, every
photograph ever taken, every song ever written, all compressed
into just 128 ones and zeros! What will these people think of next?
But then she goes on to explain the difference between lossless and
lossy compression, and eventually calls MD5 a "total loss" compression.
Not exactly an industry term, but at least she doesn't leave anyone
with the impression that a hash code can be used to compress a 100GB
hard disk into 16 bytes.
...Or does she? Will everyone that sees that page get as far as I did?
> Of course, we're in this mess because C++ lacks module
> names. Namespaces should have done the job, but they
> don't.
*** Exercises for the reader ***
Junior guru question: how long would a printable module name have to
be, in order to have approximately
340,282,366,920,938,463,463,374,607,431,768,211,455
different possible values? (For some reasonable meaning of the word
"reasonable" -- but in no case less than 90% of this number). Assume
that we will use uppercase and lowercase letters, digits, and the
underscore (_) only. (For now we'll ignore details such as whether the
first character can be an underscore or digit.)
Hint: 26+26+10+1=63 different characters. If identifiers are
1 character long, there are 63 possibilities. For 2-character
identifiers, there are 63*63 possibilities, and so on.
N-character identifiers have 63**N possibilities, where ** is
exponentiation ("to the power of").
Advanced guru question: Without bothering to compute the exact odds,
let's just take it as a given that the average module length will be
FAR less than this lofty goal. Instead, visit Hades and locate a
snowball, then come back and compute the odds of even 10 major players
(not counting compiler vendors, complaince testers, and magazine
reviewers) using a module length this long, for any reasonable
definition of the word "major".
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Tue, 5 Nov 2002 23:52:33 +0000 (UTC) Raw View
In article <7f2735a5.0211041532.5b1579d7@posting.google.com>,
on Tue, 5 Nov 2002 20:02:45 +0000 (UTC),
allan_w@my-dejanews.com (Allan W) wrote:
> Junior guru question: how long would a printable module name have to
> be, in order to have approximately
> 340,282,366,920,938,463,463,374,607,431,768,211,455
> different possible values? (For some reasonable meaning of the word
> "reasonable" -- but in no case less than 90% of this number). Assume
> that we will use uppercase and lowercase letters, digits, and the
> underscore (_) only. (For now we'll ignore details such as whether the
> first character can be an underscore or digit.)
A rough mental calculation suggests about 26 characters should be
adequate. It should also be enough to avoid using a leading _ or
digit, but might not be quite enough to avoid double _.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 22 Oct 2002 15:34:42 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0210181628.3f955ca5@posting.google.com>...
> > ""Electric Ninja"" <noway@jose.dude> wrote
> > > One thing I'd like to see in standard C++ is a preprocessor
> > > directive similar to "#pragma once" that the Microsoft compilers
> > > provide for use in header files. Maybe call it "#once" or
> > > something (who knows?).
> Personally, I like this idea. I believe that Microsoft isn't the only
> vendor that honors #pragma once, but as Carl Daniel points out, there
> are also other methods to accomplish this same thing -- it's so
> useful, and (I assume) so trivial, that it seems an obvious candidate
> for standardization.
IMHO, it would be simpler to require compilers to do this trick.
More generally, I feel that the current textual inclusion is too much of
a hack anyway. What is needed is some sort of controlled include, in
which the "included" header doesn't inherit all of the macro
definitions, etc. from previously included headers. This inclusion
could then be defined to be "once only".
> "Carl Daniel" <cpdaniel@pacbell.net> wrote
> > These days, the preferred solutiuon seems to be to make the
> > preprocessor able to recognize the "include guard" idiom, and behave
> > as-if something akin to #pragma once had been used. GCC does this,
> > for example.
> When the preprocessor is actually part of the compiler (which is
> normal these days), it should be possible to evaluate an include
> file's context while it is being parsed.
The only things of interest are the preprocessor tokens and symbols, so
whether the preprocessor is a separate program or not is irrelevant.
> It should sometimes be possible to elide a second #include when the
> file is included under conditions similar to this:
> 1. The file was already included at global or namespace level. By this
> I mean that we didn't include the file in the middle of a class or
> function definition, although it may be in the middle of a namespace
> definition, and
Where the file was included is irrelevant.
> 2. The current inclusion is also at global or same-namespace level. (If
> the previous inclusion was in the middle of a namespace definition,
> the new one has to be in the SAME namespace), and
Where the current inclusion is is irrelevant.
> 3. During the first inclusion, we found no #if statements (or maybe no
> #if statements that depend on preprocessor symbols that have changed)
> that would allow anything declared or defined to have different meaning.
The rule is actually very much simpler. If the first preprocessor
tokens after the file is opened are # followed by [if|ifdef|ifndef], the
preprocessor memorizes the line. If the file has an associated
memorized line, and the last preprocessor tokens when processing it are
# endif, the preprocessor notes this fact, along with the memorized line
(probably by putting the memorized line in a
map<filepath,memorizedLine>). Whenever the preprocessor encounters an
include directive, it checks to see whether it has a memorized first
line for it. If so, it evaluates that line; if the evaluation results
in a block which would be skipped, it doesn't even open the file.
About the only time this could fail is when the file system feeds up a
different version of the file the second time it is (or would be)
opened. I'm not sure what the standard says about this, but it's
certainly not something I can imagine counting on anyway.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 23 Oct 2002 02:13:51 +0000 (UTC) Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> What if the same file is read through different paths?
>
> This can occur through:
>
> - absolute path vs relative path
> - paths containing ".."
> - paths containing symlinks
> ...
> - paths containing URLS which connect to servers whose
> file systems have hard links, but for which the compiler
> has no way of querying the server to determine which
> files are links to other files
>
> In the general case it is very difficult for the compiler to know
> when two files are actually the same file.
Which compiler is "the compiler" that implements "the general case?"
Even for multi-platform compilers such as Comeau or GCC, some parts
of the compiler have to be recompiled to run on any new platform.
AFAIK, every platform has at least one way to tell if two given
filenames happen to refer to the same file or not.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 23 Oct 2002 02:13:52 +0000 (UTC) Raw View
> > > ""Electric Ninja"" <noway@jose.dude> wrote
> > > > One thing I'd like to see in standard C++ is a preprocessor
> > > > directive similar to "#pragma once" that the Microsoft compilers
> > > > provide for use in header files. Maybe call it "#once" or
> > > > something (who knows?).
> allan_w@my-dejanews.com (Allan W) wrote
> > Personally, I like this idea. I believe that Microsoft isn't the only
> > vendor that honors #pragma once, but as Carl Daniel points out, there
> > are also other methods to accomplish this same thing -- it's so
> > useful, and (I assume) so trivial, that it seems an obvious candidate
> > for standardization.
kanze@gabi-soft.de (James Kanze) wrote
> IMHO, it would be simpler to require compilers to do this trick.
As do I.
> More generally, I feel that the current textual inclusion is too much of
> a hack anyway. What is needed is some sort of controlled include, in
> which the "included" header doesn't inherit all of the macro
> definitions, etc. from previously included headers. This inclusion
> could then be defined to be "once only".
I like that idea, a lot.
In fact, we can take it a step further:
#off blocks all translation of preprocessor symbols until the matching
#on which turns it back on.
#if processing would still work normally.
#off and #on can nest, so that one #include file that uses it can #include
another one that also does.
The catch, of course, is when people don't realize they're using
intentionally-generated macros, such as fputs(). IMHO, not a huge catch.
> > "Carl Daniel" <cpdaniel@pacbell.net> wrote
> > > These days, the preferred solutiuon seems to be to make the
> > > preprocessor able to recognize the "include guard" idiom, and behave
> > > as-if something akin to #pragma once had been used. GCC does this,
> > > for example.
>
> > When the preprocessor is actually part of the compiler (which is
> > normal these days), it should be possible to evaluate an include
> > file's context while it is being parsed.
>
> The only things of interest are the preprocessor tokens and symbols, so
> whether the preprocessor is a separate program or not is irrelevant.
But it would be relevant, if the idea proposed below was considered.
> > It should sometimes be possible to elide a second #include when the
> > file is included under conditions similar to this:
>
> > 1. The file was already included at global or namespace level. By this
> > I mean that we didn't include the file in the middle of a class or
> > function definition, although it may be in the middle of a namespace
> > definition, and
>
> Where the file was included is irrelevant.
I was thinking specifically about "code snippet" header files.
// mainprog.cpp
void foo_always() {
#include "guts_of_foo.h"
}
void foo_if(bool condition) {
if (condition) {
#include "guts_of_foo.h"
}
}
Hopefully, this technique is very rare these days! (I used to do it in
the BASIC language in the 1980's, to bring in a "MAP" statement and a
matching file open -- I don't miss it at all.)
Nevertheless, someone might be using it today -- it's a situation where
the include-once-only concept would NOT be desired.
> > 2. The current inclusion is also at global or same-namespace level. (If
> > the previous inclusion was in the middle of a namespace definition,
> > the new one has to be in the SAME namespace), and
>
> Where the current inclusion is is irrelevant.
Same idea for different scopes. You might have boilerplate code in
several different namespaces, implemented with #include.
> > 3. During the first inclusion, we found no #if statements (or maybe no
> > #if statements that depend on preprocessor symbols that have changed)
> > that would allow anything declared or defined to have different meaning.
>
> The rule is actually very much simpler. If the first preprocessor
> tokens after the file is opened are # followed by [if|ifdef|ifndef], the
> preprocessor memorizes the line. If the file has an associated
> memorized line, and the last preprocessor tokens when processing it are
> # endif, the preprocessor notes this fact, along with the memorized line
> (probably by putting the memorized line in a
> map<filepath,memorizedLine>). Whenever the preprocessor encounters an
> include directive, it checks to see whether it has a memorized first
> line for it. If so, it evaluates that line; if the evaluation results
> in a block which would be skipped, it doesn't even open the file.
>
> About the only time this could fail is when the file system feeds up a
> different version of the file the second time it is (or would be)
> opened. I'm not sure what the standard says about this, but it's
> certainly not something I can imagine counting on anyway.
// mainprog.cpp
// Copyright 2002, SomeCompanyThatHatesTemplates Inc.
float total(float*ary, int arysize) {
float tot=0.0;
#include "total_guts.h"
return tot;
}
long total(long*ary, int arysize) {
long tot=0;
#include "total_guts.h"
return tot;
}
char ary[10];
const int arysize=10;
int tot=0;
void foo()
// Body supplied by include file -- but doesn't work in DEBUG
#undef DEBUG_TOTAL_GUTS
#include "total_guts.h"
// total_guts.h
#if defined(MSVC)
#error Not intended for Microsoft compilers
#endif
{ for (int i=0; i<arysize; ++i) tot += ary[i]; }
#if DEBUG_TOTAL_GUTS
std::cout << "Total was " << tot << std::endl;
#endif
Please note that the final #endif does not match the first #if.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 23 Oct 2002 04:32:12 +0000 (UTC) Raw View
Allan W wrote:
>>>>""Electric Ninja"" <noway@jose.dude> wrote
>>More generally, I feel that the current textual inclusion is too much of
>>a hack anyway. What is needed is some sort of controlled include, in
>>which the "included" header doesn't inherit all of the macro
>>definitions, etc. from previously included headers. This inclusion
>>could then be defined to be "once only".
>>
>
> I like that idea, a lot.
I'd thought about that, but it seems too radical.
The strict approach would be that each file referenced
with "using" has available to it only the symbols referenced
in the files it itself references with "using". Thus,
using "a";
using "b";
would not make the definitions from "a" available when "b"
was being processed. Those definitions would be hidden when
"b" was processed, using a stack-oriented dictionary.
This would make programs insensitive to
the order of "using" statements, and would make efficient header
preprocessing much more feasible.
But that's a huge change from the way C and C++ work now.
It breaks most of the schemes for configuration via the
preprocessor.
Oh, well...
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 24 Oct 2002 22:21:52 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0210221622.3bfc502d@posting.google.com>...
> > > > ""Electric Ninja"" <noway@jose.dude> wrote
> > > > > One thing I'd like to see in standard C++ is a preprocessor
> > > > > directive similar to "#pragma once" that the Microsoft compilers
> > > > > provide for use in header files. Maybe call it "#once" or
> > > > > something (who knows?).
> allan_w@my-dejanews.com (Allan W) wrote
> > > Personally, I like this idea. I believe that Microsoft isn't the only
> > > vendor that honors #pragma once, but as Carl Daniel points out, there
> > > are also other methods to accomplish this same thing -- it's so
> > > useful, and (I assume) so trivial, that it seems an obvious candidate
> > > for standardization.
> kanze@gabi-soft.de (James Kanze) wrote
> > IMHO, it would be simpler to require compilers to do this trick.
> As do I.
> > More generally, I feel that the current textual inclusion is too
> > much of a hack anyway. What is needed is some sort of controlled
> > include, in which the "included" header doesn't inherit all of the
> > macro definitions, etc. from previously included headers. This
> > inclusion could then be defined to be "once only".
> I like that idea, a lot.
> In fact, we can take it a step further:
> #off blocks all translation of preprocessor symbols until the matching
> #on which turns it back on.
> #if processing would still work normally.
> #off and #on can nest, so that one #include file that uses it can
> #include another one that also does.
I'd do it slightly differently. No additional preprocessor directives.
Basically, just compile the "included" file on the side, in a completely
new context, and integrate the results of the compilation (symbol table,
etc.) into what you are compiling. But the compilation of the included
file receives a completely new environment.
> The catch, of course, is when people don't realize they're using
> intentionally-generated macros, such as fputs(). IMHO, not a huge
> catch.
In C++, fputs cannot be a macro.
> > > "Carl Daniel" <cpdaniel@pacbell.net> wrote
> > > > These days, the preferred solutiuon seems to be to make the
> > > > preprocessor able to recognize the "include guard" idiom, and
> > > > behave as-if something akin to #pragma once had been used. GCC
> > > > does this, for example.
> > > When the preprocessor is actually part of the compiler (which is
> > > normal these days), it should be possible to evaluate an include
> > > file's context while it is being parsed.
> > The only things of interest are the preprocessor tokens and symbols,
> > so whether the preprocessor is a separate program or not is
> > irrelevant.
> But it would be relevant, if the idea proposed below was considered.
I don't think so. With the idea I sketched out above, the include
wouldn't be a preprocessor directive anyway. The included file would be
processed through phase seven, completely, as if it were separately
compiled. Then, a new phase would take place, which would introduce the
results of this compilation into the current compilation, to create a
single translation unit.
It is, of course, only one possibility. IMHO, some sort of modules
would be even better, but I'm not sure if it is doable.
> > > It should sometimes be possible to elide a second #include when
> > > the file is included under conditions similar to this:
> > > 1. The file was already included at global or namespace level. By
> > > this I mean that we didn't include the file in the middle of a
> > > class or function definition, although it may be in the middle
> > > of a namespace definition, and
> > Where the file was included is irrelevant.
> I was thinking specifically about "code snippet" header files.
> // mainprog.cpp
> void foo_always() {
> #include "guts_of_foo.h"
> }
> void foo_if(bool condition) {
> if (condition) {
> #include "guts_of_foo.h"
> }
> }
> Hopefully, this technique is very rare these days! (I used to do it in
> the BASIC language in the 1980's, to bring in a "MAP" statement and a
> matching file open -- I don't miss it at all.)
But it's still irrelevant. Such include files don't contain include
guards, and so aren't affected.
The whole point of the optimisation is that the compiler memorizes
enough information from the included file to be able to prove that
including it a second time would result in no tokens after
preprocessing. And only when it can prove this does it suppress the
second reading of the file. The ONLY visible difference for the user is
the compile times.
> Nevertheless, someone might be using it today -- it's a situation
> where the include-once-only concept would NOT be desired.
I'm sure at least one person is using it. Me. I often generate table
initializations separately, and then do something like:
static Foo const init[] =
{
#include "fooInit.hh"
} ;
(Actually, in my more recent work, I do take pains to generate complete
files separately, rather than just the bits. Namespaces mean that I can
safely put the array in a separate module without namespace pollution.
But I still have quite a bit of code like this. There's no way you're
going to get me to manually type in hundreds of arbitrary values when I
can do it automatically with a simple script.)
> > > 2. The current inclusion is also at global or same-namespace
> > > level. (If the previous inclusion was in the middle of a
> > > namespace definition, the new one has to be in the SAME
> > > namespace), and
> > Where the current inclusion is is irrelevant.
> Same idea for different scopes. You might have boilerplate code in
> several different namespaces, implemented with #include.
See above. If the entire contents of the include is withing include
guards, the effect of including it a second time will be zero. So we
don't do it. If there is even one token outside of the include guards,
the file will be included and preprocessed every time it is mentioned.
> > > 3. During the first inclusion, we found no #if statements (or
> > > maybe no #if statements that depend on preprocessor symbols
> > > that have changed) that would allow anything declared or
> > > defined to have different meaning.
> > The rule is actually very much simpler. If the first preprocessor
> > tokens after the file is opened are # followed by [if|ifdef|ifndef],
> > the preprocessor memorizes the line. If the file has an associated
> > memorized line, and the last preprocessor tokens when processing it
> > are # endif, the preprocessor notes this fact, along with the
> > memorized line (probably by putting the memorized line in a
> > map<filepath,memorizedLine>). Whenever the preprocessor encounters
> > an include directive, it checks to see whether it has a memorized
> > first line for it. If so, it evaluates that line; if the evaluation
> > results in a block which would be skipped, it doesn't even open the
> > file.
> > About the only time this could fail is when the file system feeds up
> > a different version of the file the second time it is (or would be)
> > opened. I'm not sure what the standard says about this, but it's
> > certainly not something I can imagine counting on anyway.
> // mainprog.cpp
> // Copyright 2002, SomeCompanyThatHatesTemplates Inc.
> float total(float*ary, int arysize) {
> float tot=0.0;
> #include "total_guts.h"
> return tot;
> }
> long total(long*ary, int arysize) {
> long tot=0;
> #include "total_guts.h"
> return tot;
> }
> char ary[10];
> const int arysize=10;
> int tot=0;
> void foo()
> // Body supplied by include file -- but doesn't work in DEBUG
> #undef DEBUG_TOTAL_GUTS
> #include "total_guts.h"
> // total_guts.h
> #if defined(MSVC)
> #error Not intended for Microsoft compilers
> #endif
> { for (int i=0; i<arysize; ++i) tot += ary[i]; }
> #if DEBUG_TOTAL_GUTS
> std::cout << "Total was " << tot << std::endl;
> #endif
> Please note that the final #endif does not match the first #if.
G++ gets this right, so it should be possible:-). In fact, I don't
think that it is that difficult. Obviously, you have to keep track of
which #endif belongs to which #if, but you have to do that anyway in the
preprocessor.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 24 Oct 2002 22:22:19 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0210221628.1a686868@posting.google.com>...
> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> > What if the same file is read through different paths?
> > This can occur through:
> > - absolute path vs relative path
> > - paths containing ".."
> > - paths containing symlinks
> > ...
> > - paths containing URLS which connect to servers whose
> > file systems have hard links, but for which the compiler
> > has no way of querying the server to determine which
> > files are links to other files
> > In the general case it is very difficult for the compiler to know
> > when two files are actually the same file.
> Which compiler is "the compiler" that implements "the general case?"
> Even for multi-platform compilers such as Comeau or GCC, some parts of
> the compiler have to be recompiled to run on any new platform. AFAIK,
> every platform has at least one way to tell if two given filenames
> happen to refer to the same file or not.
With NFS, even the OS generally doesn't always know. Just mount the
same file system (or even different parts of the same system) twice, at
different points, and see what happens.
Under Unix, at least, file identity can be determined via the inode
number. But this identity is only unique within a given file system.
If the OS sees the same file system twice, as if it were two different
file systems, then it has to assume that all of the files in it are
different, even if they have the same inode number.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: Fri, 25 Oct 2002 05:06:44 +0000 (UTC) Raw View
why not have "#pragma once" be a hint to the compiler that you intend
to have this file be included once, but still require the #ifdef
guard. That way, if your compiler supports "#pragma once" and it is
able to determine that a second include is identical to the first,
then it can skip the include. If not, we will be no worse off than
where we started.
Even if we were to add "#pragma once" to the language, library
developers would still need to use both systems, until everyone's
compilers got up to speed. Seeing how long that takes these days, we
can expect most library code even after the potential language change
to have both. So, why not take advantage of that fact?
joshua lehrer
factset research systems
kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0210240003.3998f30c@posting.google.com>...
> allan_w@my-dejanews.com (Allan W) wrote in message
> news:<7f2735a5.0210221628.1a686868@posting.google.com>...
> > fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> > > What if the same file is read through different paths?
>
> > > This can occur through:
>
> > > - absolute path vs relative path
> > > - paths containing ".."
> > > - paths containing symlinks
> > > ...
> > > - paths containing URLS which connect to servers whose
> > > file systems have hard links, but for which the compiler
> > > has no way of querying the server to determine which
> > > files are links to other files
>
> > > In the general case it is very difficult for the compiler to know
> > > when two files are actually the same file.
>
> > Which compiler is "the compiler" that implements "the general case?"
>
> > Even for multi-platform compilers such as Comeau or GCC, some parts of
> > the compiler have to be recompiled to run on any new platform. AFAIK,
> > every platform has at least one way to tell if two given filenames
> > happen to refer to the same file or not.
>
> With NFS, even the OS generally doesn't always know. Just mount the
> same file system (or even different parts of the same system) twice, at
> different points, and see what happens.
>
> Under Unix, at least, file identity can be determined via the inode
> number. But this identity is only unique within a given file system.
> If the OS sees the same file system twice, as if it were two different
> file systems, then it has to assume that all of the files in it are
> different, even if they have the same inode number.
>
> --
> James Kanze mailto:jkanze@caicheuvreux.com
> Conseils en informatique orient e objet/
> Beratung in objektorientierter Datenverarbeitung
>
> ---
> [ 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 ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 25 Oct 2002 16:49:16 +0000 (UTC) Raw View
usenet_cpp@lehrerfamily.com (Joshua Lehrer) writes:
>why not have "#pragma once" be a hint to the compiler that you intend
>to have this file be included once, but still require the #ifdef
>guard.
Because in that case, the #pragma once is unnecessary; if the #ifdef
guard is there, compilers can easily detect it and do the optimization
of only reading in the file once without needing any hint.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Fri, 25 Oct 2002 20:16:32 +0000 (UTC) Raw View
Allan W wrote:
> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>>What if the same file is read through different paths?
Perhaps the compilation takes longer. This isn't
a real problem.
John Nagle
Animats
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 25 Oct 2002 21:01:25 CST Raw View
nagle@animats.com (John Nagle) writes:
>> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>>>What if the same file is read through different paths?
>
> Perhaps the compilation takes longer. This isn't
>a real problem.
Many header files will result in compilation errors if they are
included twice (and not protected with an #ifndef ... #define ...
#endif guard), e.g. because they define enumeration types.
So it's not just compilation time -- it affects whether or not the
program will compile.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Sat, 26 Oct 2002 22:50:03 +0000 (UTC) Raw View
> >>>>""Electric Ninja"" <noway@jose.dude> wrote
> >>More generally, I feel that the current textual inclusion is too much of
> >>a hack anyway. What is needed is some sort of controlled include, in
> >>which the "included" header doesn't inherit all of the macro
> >>definitions, etc. from previously included headers. This inclusion
> >>could then be defined to be "once only".
> Allan W wrote:
> > I like that idea, a lot.
nagle@animats.com (John Nagle) wrote
> I'd thought about that, but it seems too radical.
>
> The strict approach would be that each file referenced
> with "using" has available to it only the symbols referenced
> in the files it itself references with "using". Thus,
>
> using "a";
> using "b";
>
> would not make the definitions from "a" available when "b"
> was being processed. Those definitions would be hidden when
> "b" was processed, using a stack-oriented dictionary.
> This would make programs insensitive to
> the order of "using" statements, and would make efficient header
> preprocessing much more feasible.
>
> But that's a huge change from the way C and C++ work now.
> It breaks most of the schemes for configuration via the
> preprocessor.
Are you referring to the common practice of creating "xxxconfig.h"
(or similar) which contains code such as
#if defined( __MSVC__ )
// Microsoft Visual C++
// Variables defined in for() statements outlive the block:
#define XXX_FOR_SCOPE 0
// Can't use partial specialization
#define XXX_PARTIAL_SPECIALIZATION 0
// ... etc...
#elif defined( __BORLANDC__ )
// and so on
#endif
Then, the program includes "xxxconfig.h" before any other include
files from vendor XXX. Is that what you're referring to?
The answer is simple -- have each of the xxx files include xxxconfig.h
directly. Yes, this is a programming change, but a very minor one, and
only to multiple-platform programs (or libraries) that use this technique.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Sat, 26 Oct 2002 22:50:14 +0000 (UTC) Raw View
allan_w@my-dejanews.com (Allan W) writes:
>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
>> What if the same file is read through different paths?
>>
>> This can occur through:
>>
>> - absolute path vs relative path
>> - paths containing ".."
>> - paths containing symlinks
>> ...
>> - paths containing URLS which connect to servers whose
>> file systems have hard links, but for which the compiler
>> has no way of querying the server to determine which
>> files are links to other files
>>
>> In the general case it is very difficult for the compiler to know
>> when two files are actually the same file.
>
>Which compiler is "the compiler" that implements "the general case?"
Any compiler on a system that supports network file systems is going
to encounter this issue. How can the compiler tell whether
two files that are accessed by two different network paths
are actually the same file? Whether or not they are the
same file depends on the behaviour of the file server.
>AFAIK, every platform has at least one way to tell if two given
>filenames happen to refer to the same file or not.
I'm pretty sure you're wrong about that. How can you tell if two
filenames on network file systems such as NFS or SMB are the same file?
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Sat, 26 Oct 2002 22:50:27 +0000 (UTC) Raw View
Allan W wrote:
> AFAIK, every platform has at least one way to tell if two given
> filenames happen to refer to the same file or not.
My Windows 2000 machine has local filesystems, directories mounted
from UNIX filesystems via Samba, directories mounted from other
Windows machines, and virtual filesystems maintained by ClearCase
for source-code control. I am not as nearly certain as you that it
is possible to know that two files are in fact the same, or even
what "the same" means in all cases.
Fortunately, the include guard method makes that irrelevant.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Sat, 26 Oct 2002 22:54:27 +0000 (UTC) Raw View
In article <apcsel$677$1@mulga.cs.mu.OZ.AU>,
on Fri, 25 Oct 2002 21:01:25 CST,
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote:
> nagle@animats.com (John Nagle) writes:
>
> > Perhaps the compilation takes longer. This isn't
> >a real problem.
>
> Many header files will result in compilation errors if they are
> included twice (and not protected with an #ifndef ... #define ...
> #endif guard), e.g. because they define enumeration types.
> So it's not just compilation time -- it affects whether or not the
> program will compile.
Which is exactly the reason they should have include guards.
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cbarron3@ix.netcom.com (Carl Barron)
Date: Mon, 21 Oct 2002 16:04:37 +0000 (UTC) Raw View
"Electric Ninja" <noway@jose.dude> wrote:
> One thing I'd like to see in standard C++ is a preprocessor directive
> similar to "#pragma once" that the Microsoft compilers provide for use in
> header files. Maybe call it "#once" or something (who knows?).
>
> The neat thing about it is that you don't have to have keep writing huge
> #ifndef/#define/#endif enclosures when your purpose is to ensure that a
> header file is parsed only once. This is almost always the case with header
> files anyway. You don't have to create __MYFILE_H macros all the time.
> Also, the preprocessor as a result knows automatically not to look at the
> header file again, which saves the effort of opening it, parsing it, etc
> etc.
>
> -
I see no problem with pragma once, a compiler should know where the
include file it is reading is, and should be able to store such path
info of every file it has included. A simple search of this cache of
read paths and if its there just return as if it was read. If there is
no #pragma all is the same before 100% backward compatible, as soon as
the compiler must dispose of header info, it removes the path as well,
does not seem to take rocket science to recognise
"^[ \t]*#[ \t]*pragma[ \t]+once[ \t]*\n" does it???
I gusss that this is more simple to parse:)
^[ \t]*#[ \t]*ifdef[ \t]+\([^ \t\n]+\)[ \t]*\n[ \t\n]*#[ \t]*define[
\t]+\\1[ \t]*\n
// BOF
#ifndef SEXY_FEELING
#define SEXY_FEELING
// .... lots of code
#elif
#include "sey.people.h"
#endif
// more code ...
// EOF
I don't see backward compatibility problems but lots of user generated
problems with guard names, and lots of cycles wasted parsing #if*/#endif
pairs under the current standard...
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Mon, 21 Oct 2002 17:14:20 +0000 (UTC) Raw View
> ""Electric Ninja"" <noway@jose.dude> wrote
> > One thing I'd like to see in standard C++ is a preprocessor directive
> > similar to "#pragma once" that the Microsoft compilers provide for use in
> > header files. Maybe call it "#once" or something (who knows?).
Personally, I like this idea. I believe that Microsoft isn't the only
vendor that honors #pragma once, but as Carl Daniel points out, there are
also other methods to accomplish this same thing -- it's so useful, and
(I assume) so trivial, that it seems an obvious candidate for
standardization.
"Carl Daniel" <cpdaniel@pacbell.net> wrote
> These days, the preferred solutiuon seems to be to make the preprocessor
> able to recognize the "include guard" idiom, and behave as-if something akin
> to #pragma once had been used. GCC does this, for example.
When the preprocessor is actually part of the compiler (which is normal
these days), it should be possible to evaluate an include file's context
while it is being parsed. It should sometimes be possible to elide a
second #include when the file is included under conditions similar to this:
1. The file was already included at global or namespace level. By this
I mean that we didn't include the file in the middle of a class or
function definition, although it may be in the middle of a namespace
definition, and
2. The current inclusion is also at global or same-namespace level. (If
the previous inclusion was in the middle of a namespace definition,
the new one has to be in the SAME namespace), and
3. During the first inclusion, we found no #if statements (or maybe no
#if statements that depend on preprocessor symbols that have changed)
that would allow anything declared or defined to have different meaning.
...and maybe a few other rules like this. Note that this is exactly the
same process that a human programmer ought to consider before introducing
"include guards" in the first place. Furthermore, it would apply to the
vast majority of traditional include files, except for include files that
already have include-guards (since by definition this makes the whole
include-file dependant on a preprocessor symbol).
However, this is a QOI issue by definition -- this is not a language
change, but a new optimization.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 22 Oct 2002 04:55:15 +0000 (UTC) Raw View
cbarron3@ix.netcom.com (Carl Barron) writes:
> I see no problem with pragma once, a compiler should know where the
>include file it is reading is, and should be able to store such path
>info of every file it has included. A simple search of this cache of
>read paths and if its there just return as if it was read.
What if the same file is read through different paths?
This can occur through:
- absolute path vs relative path
- paths containing ".."
- paths containing symlinks
...
- paths containing URLS which connect to servers whose
file systems have hard links, but for which the compiler
has no way of querying the server to determine which
files are links to other files
In the general case it is very difficult for the compiler to know
when two files are actually the same file.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: noway@jose.dude ("Electric Ninja")
Date: Fri, 18 Oct 2002 11:49:00 +0000 (UTC) Raw View
One thing I'd like to see in standard C++ is a preprocessor directive
similar to "#pragma once" that the Microsoft compilers provide for use in
header files. Maybe call it "#once" or something (who knows?).
The neat thing about it is that you don't have to have keep writing huge
#ifndef/#define/#endif enclosures when your purpose is to ensure that a
header file is parsed only once. This is almost always the case with header
files anyway. You don't have to create __MYFILE_H macros all the time.
Also, the preprocessor as a result knows automatically not to look at the
header file again, which saves the effort of opening it, parsing it, etc
etc.
--
Joshua A. Schaeffer
Software Engineer (Win32/MFC, C/C++)
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Fri, 18 Oct 2002 10:40:34 CST Raw View
""Electric Ninja"" <noway@jose.dude> wrote in message
news:5APr9.101853$Cz.11181056@twister.neo.rr.com...
> One thing I'd like to see in standard C++ is a preprocessor directive
> similar to "#pragma once" that the Microsoft compilers provide for use in
> header files. Maybe call it "#once" or something (who knows?).
>
> The neat thing about it is that you don't have to have keep writing huge
> #ifndef/#define/#endif enclosures when your purpose is to ensure that a
> header file is parsed only once. This is almost always the case with
header
> files anyway. You don't have to create __MYFILE_H macros all the time.
> Also, the preprocessor as a result knows automatically not to look at the
> header file again, which saves the effort of opening it, parsing it, etc
> etc.
These days, the preferred solutiuon seems to be to make the preprocessor
able to recognize the "include guard" idiom, and behave as-if something akin
to #pragma once had been used. GCC does this, for example.
By the way, __MYFILE_H is not a name that you can legally use for an include
guard - all names containing double underscores are reserved to the
implementation. When you work on a sufficiently large project, such guards
are also insufficient, since they're not unique enough (it's not uncommon to
have multiple files with the same base name). Some people (e.g. David
Abrahams, myself) recommend using a much more specific guard, such as
filename_h_xxx_mmddyy_hhmm
where xxx are your initials, mmddyy is the date and hhmm is the time.
This guard is almost 100% guaranteed to never be duplicated, no matter how
larger the project or how many people are working on it. The MFC class
wizard actually puts a GUID into include guards to protect against this same
concern.
-cd
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]