--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGz9X0c%3DCNLVEGgJ7%3DGJ2W%2B7fsvN7h%2BtbiFyf5Cx3aab0Xb%3DrQ%40mail.gmail.com.
Please do your due diligence before making claims like this, or, for
that matter, asking for "obvious" features. I can assure you, this is
not the first time someone has asked to standardize #pragma once.
The problem, besides that the C++ language says nothing about headers in
the first place, is that determining if a header has been included or
not is much more complicated than you think, even on platforms that
*actually have a file system* (which is _not_ a requirement for a C++
compiler!).
What should happen if you include the same header (same inode) via
different names? What about if the compiler sees two identical include
directives (same path, same <> vs. "") that resolve to different files
with different contents? What about platforms with esoteric file
systems, or *no* file system?
Yes, there are implementations that "mostly work", but there is a higher
bar for standardization. Any serious proposal needs to address the
problems that have been raised historically. Claims / requests like
"compilers already do this, why not just make it official" are inadequate.
On Wednesday, October 26, 2016 at 4:52:45 PM UTC+2, Matthew Woehlke wrote:Please do your due diligence before making claims like this, or, for
that matter, asking for "obvious" features. I can assure you, this is
not the first time someone has asked to standardize #pragma once.
So you are saying this is a common request from the community, which is not being answered by the standards committee because ...?
The problem, besides that the C++ language says nothing about headers in
the first place, is that determining if a header has been included or
not is much more complicated than you think, even on platforms that
*actually have a file system* (which is _not_ a requirement for a C++
compiler!).
You're reading a really strange copy of the standard then. Mine has a table of "C++ library headers", and a definition what a header-name is.
And a great portion of it is dedicated to describing all those headers. Perhaps you are confused by the fact that headers do not have to be files?
What should happen if you include the same header (same inode) via
different names? What about if the compiler sees two identical include
directives (same path, same <> vs. "") that resolve to different files
with different contents? What about platforms with esoteric file
systems, or *no* file system?
This is an attempt at complication of a painfully simple feature.
You don't want it, so you just ask meaningless questions that have trivial answers in the hope of convincing others it is all incredibly complicated, while it really isn't.
As for answers: it doesn't matter, as long as some kind of deterministic behaviour is specified. I don't see a problem with including a file twice if a symlink exists; after all, you could just copy it and include it twice that way as well. Nobody is asking for a text comparison (or heaven forbid, a semantic comparison). I have some trouble imagining how the same header name could resolve to two different files during the same compilation. And the presence of a file system does not matter - one way or another, headers are found and read by the compiler. That process can be influenced using #pragma once, based on nothing more than the h-char-sequence or q-char-sequence of the header name.
The whole thing is completely trivial, widely used, and supported in all but one modern C++ compilers.
You're reading a really strange copy of the standard then. Mine has a table of "C++ library headers", and a definition what a header-name is.
At no point does the standard specify that "header-names" are files on a file system. They are merely "header-names".
This is an attempt at complication of a painfully simple feature.
And yet, this complication is precisely the problem.
With include guards, the question is effectively moot. Every user does their best to avoid include guard clashing, so there is no question of what "same file" means. It means having included that define.
Yes, #pragma once works in the most common cases: basic loose files without any hard-links or whatever. But not everyone does that. So what should the behavior of #pragma once be in that circumstance?
The standard specifies behavior. If some behavior cannot be fully pinned down, then the standard cannot specify what happens.
You don't want it, so you just ask meaningless questions that have trivial answers in the hope of convincing others it is all incredibly complicated, while it really isn't.
As for answers: it doesn't matter, as long as some kind of deterministic behaviour is specified. I don't see a problem with including a file twice if a symlink exists; after all, you could just copy it and include it twice that way as well. Nobody is asking for a text comparison (or heaven forbid, a semantic comparison). I have some trouble imagining how the same header name could resolve to two different files during the same compilation. And the presence of a file system does not matter - one way or another, headers are found and read by the compiler. That process can be influenced using #pragma once, based on nothing more than the h-char-sequence or q-char-sequence of the header name.
So you want #pragma once to work based on just the character sequence in the include? So in one file, I #include a file with a directory ("ghl/some_file.h"). But for files in the "ghl" directory, there would be no need for such a directory. So by your reasoning, "ghl/some_file.h" would be considered different from "some_file."h
> Nobody is asking for a text comparison (or
> heaven forbid, a semantic comparison). I have some trouble imagining how
> the same header name could resolve to two different files during the
> same compilation.
The same header can be accessible by different header-name tokens,
depending on where it is included from and what -I switches were
specified. Conversely, the same header-name may resolve to different
headers depending on the implementation and where they are included from.
FWIW, #pragma once was broken in gcc prior to 3.4, it was "confused by
symlinks and hardlinks" [1] before that. The bug is long fixed, but it
indicates that those "historical problems" are not imaginary. You may
also google around and see a few more recent bugs related to #pragma
once, like this[2] for example.
On Wednesday, October 26, 2016 at 6:24:12 PM UTC+2, Nicol Bolas wrote:This is an attempt at complication of a painfully simple feature.
And yet, this complication is precisely the problem.
With include guards, the question is effectively moot. Every user does their best to avoid include guard clashing, so there is no question of what "same file" means. It means having included that define.
If you throw the whole issue into the lap of the user you end up with the exact same problem, reversed: what if two different files have the same include guards? This has actually happened to me - I mistakenly put the same include guards into two different files. Silly mistake, but it certainly made for some interesting debugging... The two situations are symmetric, but #pragma once has a clear performance advantage (since there is no need to re-parse the entire header to find out whether what look like include guards, really are), not to mention having much cleaner semantics.
Yes, #pragma once works in the most common cases: basic loose files without any hard-links or whatever. But not everyone does that. So what should the behavior of #pragma once be in that circumstance?
You're throwing out the baby with the bath water. Any project that has some weird setup where the same header is included multiple times into the same compilation unit through hardlinks can still use include guards.
Everybody else can use #pragma once. Or if you truly think it's an issue, make the compiler finds whatever passes for a unique identifier for includeable objects (whether they are files or not), and use that as your identifier. That will work for everyone.
The standard specifies behavior. If some behavior cannot be fully pinned down, then the standard cannot specify what happens.
Don't make me laugh. The standard is absolutely chockful of implementation defined situations, not to mention throwing around undefined behaviours like they were going out of style. Adding one more bit of implementation-defined behaviour will not make a difference.
Apparently (disclaimer: I am repeating statements made elsewhere, though
I think I can guess the underlying reasoning) this is harder than you
think. I suspect that computing a hash of the file is the only reliable
method. (We'll assume the contents are at least constant during
compilation, since if they aren't, you're probably doomed no matter what.)
If this has been argued to death before, please provide links to the discussion to prove
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b8be250d-a282-4a39-b07a-03c45d743521%40isocpp.org.
But one thing does make me wonder. A previous post mentioned using #pragma once as a marker for the compiler to compute hashes of the content. I wonder whether it's faster to compute said hash than to scan for the header guard.
Because if it is, we do have a portable and reliable way of making preventing multiple inclusion of headers containing #pragma once. The standard doens't even have to specify *how* the identity is established, only that the content of a header that contains #pragma once must only be processed once per TU. It won't prevent the overhead of opening and reading the file but that's just the status quo with guards anyway.
On 28 Oct 2016, at 11:50 , Andrey Semashev <andrey....@gmail.com> wrote:On 10/28/16 02:48, Miro Knejp wrote:Am 28.10.2016 um 01:06 schrieb Andrey Semashev:>On Fri, Oct 28, 2016 at 1:17 AM, Nevin Liber <ne...@eviloverlord.com>
wrote:3. The OS doesn't know if the files have the same content. I'mAs I shown earlier, basing the decision on the hash can result in
pretty sure
this would require an extra pass to compute the fingerprint hash, as you
shouldn't be processing the file until you are sure it is unique.
You still
have to scan for include guards as that is just normal macro processing.
incorrect result. IMO, content equivalence is not the right criteria
for skipping file inclusion.Your example doesn't work precisely *because* the behavior of #pragma
once isn't specified. Anyone can come up with a contrived example that
breaks a feature which hasn't been defined yet, implying the feature
must be impossible because it cannot solve an artificial use case it
probably isn't even designed to solve.
That example breaks assuming #once relies on hashing the header, which is what you suggested above.
If such a utility is added (whatever it ends up being called) and it has
clearly defined rules then this "trick" only works if it conforms to the
rules of the new feature. If it doesn't then you have to simply resolve
to include guards for such preprocessor voodoo. But at that point you as
the author of the project know whether you can use this feature or not
because it has (hopefully) clearly specified behavior and as such you
should then know whether or not you can setup your files the way described.It unfortunately doesn't solve the problem of having to come up wth a
I think a proposal similar to the previously mentioned "#once
guard_phrase" has more potential. It does give the user a way to
indicate file equivalence (through the guard name) and also is
arguably less expensive than computing a hash value.
guard that is unique within the multiverse. For example boost_date_time
has an include guard called ISO_FORMAT_HPP___. That's not exactly the
most unique guard in the world. The less this relies on human
(non-)creativity or discipline the better.
The important benefit of that approach is that the user is still in control to solve the issue - he can simply modify the guard to be more unique. You could argue that the user could modify any part of the header to change its hash, and that's true. But as a user of the library, I would be much more confident modifying the guard - the element that is precisely aimed at solving the problem - than any unrelated part of the header, even a comment.Like many modern C++ improvements it's trying to create a sensible
default. If that default doesn't work for (hopefully rare) use cases
then you can always revert to the previous method.
The problem with the "if it doesn't work for you, use the traditional include guards" argument is that it doesn't work for library developers because they generally don't know how their library will be used and whether #once can fail in those conditions. If #once doesn't offer the same degree of portability as include guards, the latter are always preferable and there simply is no reason to use #once.
import std.vector;
On Fri, Oct 28, 2016 at 1:17 AM, Nevin Liber <ne...@eviloverlord.com> wrote:
>
> There are three possibilities:
>
> 1. It is the same file according to the OS (e.g.: inode and device match).
> 2. It must have different contents according to the OS (e.g. the size doesn't
> match).
I think, the above two bullets cannot be implemented reliably. Event
the size may not be available if the source is read from a pipe.
I think a proposal similar to the previously mentioned "#once
guard_phrase" has more potential.
Pragma once has other problems, like nobody has cared to specify what it means on systems other than Linux and Windows.
And should the compiler writer be required to test the feature on every other file system that can possibly be mounted on your development system?
The copy-paste error with the include guard has the advantage that you can fix it yourself.
I generally agree. Standardizing pragma once makes sense. In fact, it makes so much sense that I think it's worthwhile putting in the elbow grease and solving the issues that arise as part of the "spring cleaning"
What's the point of spending time on solving a problem that will become increasingly less relevant? Especially since we already have a solution that, while not perfect, is still entirely adequate.
Point well made.What's the point of spending time on solving a problem that will become increasingly less relevant? Especially since we already have a solution that, while not perfect, is still entirely adequate.I think that it will still be relevant for quite some time yet - especially for newcomers, who I think would benefit the most from #pragma once. At least, I can't imagine that they'll be using modules.