Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pragma once support

276 views
Skip to first unread message

woodb...@gmail.com

unread,
Nov 29, 2018, 2:40:04 PM11/29/18
to
Shalom

One of the comments in this thread:
https://www.reddit.com/r/cpp/comments/a14o5q/real_world_problems_with_pragma_once/

said that Cray doesn't support pragma once. I know gcc,
Clang and MSVC do support it. I was wondering if Intel,
IBM or Oracle compilers support it.

In my software:
https://github.com/Ebenezer-group/onwards

I've been using pragma once for a number of years, but
maybe I should switch to using include guards. In the
past I had more include files, but now just have a few,
so switching to include guards would be easy.
Thank you in advance.


Brian
Ebenezer Enterprises - Enjoying programming again.
http://webEbenezer.net

David Brown

unread,
Nov 29, 2018, 3:47:46 PM11/29/18
to
On 29/11/2018 20:39, woodb...@gmail.com wrote:
> Shalom
>
> One of the comments in this thread:
> https://www.reddit.com/r/cpp/comments/a14o5q/real_world_problems_with_pragma_once/
>
> said that Cray doesn't support pragma once. I know gcc,
> Clang and MSVC do support it. I was wondering if Intel,
> IBM or Oracle compilers support it.
>
> In my software:
> https://github.com/Ebenezer-group/onwards
>
> I've been using pragma once for a number of years, but
> maybe I should switch to using include guards. In the
> past I had more include files, but now just have a few,
> so switching to include guards would be easy.
> Thank you in advance.

I think "#pragma once" is supported by most compilers, but include
guards are supported by /all/ compilers. I would expect performance of
them to be very similar - I know gcc has short-circuit paths in the
pre-processor to make handling of include guards as efficient as possible.

Include guards are standard, "#pragma once" is not, but it is so common
that it is unlikely ever to be an issue. I'd not bother changing,
unless someone complains about it not working with their compiler.

>
>
> Brian
> Ebenezer Enterprises - Enjoying programming again.

I am glad to hear you are enjoying your programming again. I expect
most of us have been enjoying it since we started. Did you go through a
bad period where programming was an unpleasant chore for you?

Vir Campestris

unread,
Nov 29, 2018, 4:56:39 PM11/29/18
to
On 29/11/2018 20:47, David Brown wrote:
> I think "#pragma once" is supported by most compilers, but include
> guards are supported by /all/ compilers.  I would expect performance of
> them to be very similar - I know gcc has short-circuit paths in the
> pre-processor to make handling of include guards as efficient as possible.
>
> Include guards are standard, "#pragma once" is not, but it is so common
> that it is unlikely ever to be an issue.  I'd not bother changing,
> unless someone complains about it not working with their compiler.

To be fast, and standard compliant, I use both.

Andy

Alf P. Steinbach

unread,
Nov 29, 2018, 8:58:45 PM11/29/18
to
On 29.11.2018 20:39, woodb...@gmail.com wrote:
> Shalom
>
> One of the comments in this thread:
> https://www.reddit.com/r/cpp/comments/a14o5q/real_world_problems_with_pragma_once/
>
> said that Cray doesn't support pragma once.

There is a table in Wikipedia, <url:
https://en.wikipedia.org/wiki/Pragma_once#Portability>.

> I know gcc,
> Clang and MSVC do support it. I was wondering if Intel,
> IBM or Oracle compilers support it.

Intel yes, IBM yes since version 3.1.1, Oracle yes since dev studio
version 12.5, all according to that table.


[snip]


Cheers!,

- Alf

woodb...@gmail.com

unread,
Nov 29, 2018, 11:06:44 PM11/29/18
to
I downloaded the Nvidia/Portland Group compiler. It also
handles pragma once. It produces chubby text segments,
though compared to gcc or even clang.


Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net



David Brown

unread,
Nov 30, 2018, 2:38:15 AM11/30/18
to
That may limit the speed advantages of both, depending on the compiler
and on the order you have them. It's not going to make much difference
(either way, you skip compilation - and preprocessing is generally very
fast).

I can appreciate that some people think "#pragma once" is neater than
include guards, and so choose to use it. And I can appreciate people
choosing include guards, as they are standard and supported everywhere.
But using both kind of defeats the purpose - it combines the
disadvantages of both methods.

> Andy

Öö Tiib

unread,
Nov 30, 2018, 4:46:49 AM11/30/18
to
It is hard to find conforming compilers that do not support
pragma once.

There can be issue with projects where there are copies of
same header; when more than one of those end up included
to same cpp file then pragma once and include guards
handle it differently.

Bonita Montero

unread,
Nov 30, 2018, 11:45:45 AM11/30/18
to
> I think "#pragma once" is supported by most compilers, but include
> guards are supported by /all/ compilers.  I would expect performance
> of them to be very similar - ...

Thinking about the efficiency of #pragma once or include-guards is
idiotic.

Vir Campestris

unread,
Nov 30, 2018, 4:48:02 PM11/30/18
to
On 30/11/2018 16:45, Bonita Montero wrote:
> Thinking about the efficiency of #pragma once or include-guards is
> idiotic.

When your compile cycle takes 35 minutes using Icecream and a pool of a
couple of hundred CPUs you care.

Andy

Vir Campestris

unread,
Nov 30, 2018, 4:49:35 PM11/30/18
to
On 30/11/2018 09:46, Öö Tiib wrote:
> There can be issue with projects where there are copies of
> same header; when more than one of those end up included
> to same cpp file then pragma once and include guards
> handle it differently.

I can't think of any reasonable case where they would.

(unreasonable? two files with the same guard name??)

Andy

Alf P. Steinbach

unread,
Nov 30, 2018, 4:59:43 PM11/30/18
to
Did you try Lakos external include guards?

Cheers!,

- Alf


Alf P. Steinbach

unread,
Nov 30, 2018, 5:12:34 PM11/30/18
to
Generally a local file can be identified by volume id and file id within
the volume. This means that with a compiler with some smarts in its file
identification scheme a /copy/ B of a local file A will not be viewed as
the same file as A. One hypothetical way that that could happen is when
a 3rd party library L that you're using bundles a library M header it
uses, when you're also using library M directly.

A second scenario can be when it's difficult to identify a file residing
on a different host on the local network, or even out in the cloud.

However, in the Reddit thread referred to by Brian, AFAICS nobody
reported ever actually having had problems with `#pragma once`, but some
reported having had problems with ordinary include guards, in particular
stemming from the not uncommon technique of copy-and-modify programming.


Cheers!,

- Alf

Bonita Montero

unread,
Dec 1, 2018, 10:33:09 AM12/1/18
to

>> Thinking about the efficiency of #pragma once or include-guards is
>> idiotic.

> When your compile cycle takes 35 minutes using Icecream and a pool
> of a couple of hundred CPUs you care.

I'll bet my right hand that parsing the C++-source and generating
code takes magnitudes more CPU-time than parsing and branching upon
the include-guards.

Vir Campestris

unread,
Dec 2, 2018, 4:58:25 PM12/2/18
to
I benchmarked this at my last company.

One order, maybe. Two - no. It was scary how long it took opening those
files. Mind, this was on spinning rust.

Andy

Vir Campestris

unread,
Dec 2, 2018, 4:58:31 PM12/2/18
to
On 30/11/2018 21:59, Alf P. Steinbach wrote:
> Did you try Lakos external include guards?

Never heard of them. And now I've looked - no. And I don't intend to.
It's bad enough making sure a copy of a file has an updated guard name
without copying those guard names into a load of source files.

<fx looks down> I've not (yet) been bitten by having two versions of a
3rd party library in the source tree, and if I found that I'd be trying
to dump one of the versions.

Andy

Jorgen Grahn

unread,
Dec 2, 2018, 5:29:24 PM12/2/18
to
The rust shouldn't matter much, since these headers quickly end up in
the disk cache -- on Unix anyway, with adequate amounts of RAM.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

David Brown

unread,
Dec 2, 2018, 5:36:06 PM12/2/18
to
If he is using Windows (at least Win7 and before - I haven't used any
later versions enough to comment about them), it /does/ matter. Windows
file caching is ridiculously bad, and it will re-read them from the disk
most of the time.


Öö Tiib

unread,
Dec 3, 2018, 7:28:22 AM12/3/18
to
All we are to certain extent ignorant, naive and fallible.
Sometimes we solve something using some unreasonable
way that works at first and only later causes complications.
The project where I saw several copies of same header
was such because it contained lot of different independent
optional dll modules that were made by different teams.
Sometimes there were copies of same headers made,
perhaps for to simplify work with those in separation.

Scott Lurndal

unread,
Dec 3, 2018, 9:11:28 AM12/3/18
to
What operating system? Windows file operations are pathetically slow.

Vir Campestris

unread,
Dec 3, 2018, 4:11:04 PM12/3/18
to
On 03/12/2018 14:11, Scott Lurndal wrote:
> What operating system? Windows file operations are pathetically slow.

Windows running in a VM!

Andy

Juha Nieminen

unread,
Dec 4, 2018, 5:01:24 AM12/4/18
to
David Brown <david...@hesbynett.no> wrote:
> I can appreciate that some people think "#pragma once" is neater than
> include guards, and so choose to use it. And I can appreciate people
> choosing include guards, as they are standard and supported everywhere.
> But using both kind of defeats the purpose - it combines the
> disadvantages of both methods.

I like the approach that Objective-C(++) supports, which is to add a new
preprocessor directive, #import, as an alternative to #include. The former
works like the latter, except that it implicitly behaves as if the file
being included has a #pragma once. Thus you don't need to write any sort
of include guard in your headers (or any other files that you might be
including).

It might not sound like much, but it's actually pretty handy once you
get used to it. I wish standard C++ introduced the same directive.

David Brown

unread,
Dec 4, 2018, 6:21:18 AM12/4/18
to
One day, one happy day, we will have C++ modules that will handle this
functionality.

In the meantime, include guards are simple, portable, reliable,
efficient, and supported by all compilers. I have never felt the need
for #pragma once, nor #import (which some C and C++ tools support).

Manfred

unread,
Dec 4, 2018, 8:42:59 AM12/4/18
to
#import has been used for a long time by Microsoft compilers to import
COM type libraries. Given that, it is unlikely that it will ever make
into the standard.

Besides, I think the meaning that you suggest for #import is too much of
a duplicate of the standard's #include, so it would not be worth a new
standardized directive.

woodb...@gmail.com

unread,
Dec 5, 2018, 3:09:10 PM12/5/18
to
At first I thought this was of no use to me, but then
realized I could use it in my private (closed-source)
code. I've tried it now with gcc and it works. I
added -Wno-deprecated to get a warning to turn off.
I encourage people to work on closed-source code.
There's nothing wrong with open-source, but closed-
source is more interesting.



Brian
Ebenezer Enterprises
http://webEbenezer.net

David Brown

unread,
Dec 5, 2018, 3:46:44 PM12/5/18
to
On 05/12/2018 21:09, woodb...@gmail.com wrote:
> On Tuesday, December 4, 2018 at 4:01:24 AM UTC-6, Juha Nieminen wrote:
>> David Brown <david...@hesbynett.no> wrote:
>>> I can appreciate that some people think "#pragma once" is neater than
>>> include guards, and so choose to use it. And I can appreciate people
>>> choosing include guards, as they are standard and supported everywhere.
>>> But using both kind of defeats the purpose - it combines the
>>> disadvantages of both methods.
>>
>> I like the approach that Objective-C(++) supports, which is to add a new
>> preprocessor directive, #import, as an alternative to #include. The former
>> works like the latter, except that it implicitly behaves as if the file
>> being included has a #pragma once. Thus you don't need to write any sort
>> of include guard in your headers (or any other files that you might be
>> including).
>>
>> It might not sound like much, but it's actually pretty handy once you
>> get used to it. I wish standard C++ introduced the same directive.
>
> At first I thought this was of no use to me, but then
> realized I could use it in my private (closed-source)
> code. I've tried it now with gcc and it works. I
> added -Wno-deprecated to get a warning to turn off.

Yes, it works with gcc. But it is non-standard, deprecated, and
pointless. Why on earth would you want to use it?

> I encourage people to work on closed-source code.
> There's nothing wrong with open-source, but closed-
> source is more interesting.
>

We all know there is nothing wrong with either open source or closed
source development - each have their place and their pros and cons.

woodb...@gmail.com

unread,
Dec 5, 2018, 10:02:15 PM12/5/18
to
On Wednesday, December 5, 2018 at 2:46:44 PM UTC-6, David Brown wrote:
> On 05/12/2018 21:09, woodb...@gmail.com wrote:
> > On Tuesday, December 4, 2018 at 4:01:24 AM UTC-6, Juha Nieminen wrote:
> >>
> >> I like the approach that Objective-C(++) supports, which is to add a new
> >> preprocessor directive, #import, as an alternative to #include. The former
> >> works like the latter, except that it implicitly behaves as if the file
> >> being included has a #pragma once. Thus you don't need to write any sort
> >> of include guard in your headers (or any other files that you might be
> >> including).
> >>
> >> It might not sound like much, but it's actually pretty handy once you
> >> get used to it. I wish standard C++ introduced the same directive.
> >
> > At first I thought this was of no use to me, but then
> > realized I could use it in my private (closed-source)
> > code. I've tried it now with gcc and it works. I
> > added -Wno-deprecated to get a warning to turn off.
>
> Yes, it works with gcc. But it is non-standard, deprecated, and
> pointless. Why on earth would you want to use it?
>

The standard doesn't plague closed-source code as
much as it does open-source code.

I wouldn't call #import pointless. It's a step in
the right direction.


Brian
Ebenezer Enterprises - In G-d we trust.
https://github.com/Ebenezer-group/onwards

David Brown

unread,
Dec 6, 2018, 2:13:03 AM12/6/18
to
On 06/12/2018 04:02, woodb...@gmail.com wrote:
> On Wednesday, December 5, 2018 at 2:46:44 PM UTC-6, David Brown wrote:
>> On 05/12/2018 21:09, woodb...@gmail.com wrote:
>>> On Tuesday, December 4, 2018 at 4:01:24 AM UTC-6, Juha Nieminen wrote:
>>>>
>>>> I like the approach that Objective-C(++) supports, which is to add a new
>>>> preprocessor directive, #import, as an alternative to #include. The former
>>>> works like the latter, except that it implicitly behaves as if the file
>>>> being included has a #pragma once. Thus you don't need to write any sort
>>>> of include guard in your headers (or any other files that you might be
>>>> including).
>>>>
>>>> It might not sound like much, but it's actually pretty handy once you
>>>> get used to it. I wish standard C++ introduced the same directive.
>>>
>>> At first I thought this was of no use to me, but then
>>> realized I could use it in my private (closed-source)
>>> code. I've tried it now with gcc and it works. I
>>> added -Wno-deprecated to get a warning to turn off.
>>
>> Yes, it works with gcc. But it is non-standard, deprecated, and
>> pointless. Why on earth would you want to use it?
>>
>
> The standard doesn't plague closed-source code as
> much as it does open-source code.

The standard does not "plague" open source or closed source code. But
with closed source code, you usually have a lot more control over
details of which compiler you are using (though you can happily specify
that in open source too).

>
> I wouldn't call #import pointless. It's a step in
> the right direction.
>

Yes, #import is pointless. It does nothing that you can't do with
include guards. The time saving from #import compared to include guards
is /tiny/ - and if you have a decent OS and a decent compiler, /really/
tiny.

To quote from the gcc preprocessor manual - "#import is not a well
designed feature".

It does not make sense to use it in any code - private or public.

woodb...@gmail.com

unread,
Dec 6, 2018, 3:13:43 PM12/6/18
to
The part about it being tiny sounds right.

>
> To quote from the gcc preprocessor manual - "#import is not a well
> designed feature".
>
> It does not make sense to use it in any code - private or public.

I like that I can remove the #pragma once or include guards. It
isn't a big thing, but it's something.

james...@alumni.caltech.edu

unread,
Dec 6, 2018, 3:43:13 PM12/6/18
to
On Thursday, December 6, 2018 at 3:13:43 PM UTC-5, woodb...@gmail.com wrote:
> On Thursday, December 6, 2018 at 1:13:03 AM UTC-6, David Brown wrote:
> > On 06/12/2018 04:02, woodb...@gmail.com wrote:
> > > On Wednesday, December 5, 2018 at 2:46:44 PM UTC-6, David Brown wrote:
...
> > >> Yes, it works with gcc. But it is non-standard, deprecated, and
> > >> pointless. Why on earth would you want to use it?
...
> > To quote from the gcc preprocessor manual - "#import is not a well
> > designed feature".
> >
> > It does not make sense to use it in any code - private or public.
>
> I like that I can remove the #pragma once or include guards. It
> isn't a big thing, but it's something.

The term "deprecated" implies that they expect to eventually drop
support for this feature. When they do, you're going to have to remove
#import and add either #pragma once or include guards anyway. You're not avoiding that work, you're just putting it off till later. You'll save
yourself work (admittedly, only a small amount) in the long run if you
stop using #import now. That will also reduce the amount of rush
re-writing you'll have to do once they do come out with a version that
no longer supports it.

woodb...@gmail.com

unread,
Dec 6, 2018, 9:46:03 PM12/6/18
to
From what I can tell it has been deprecated for decades:

Here:
https://stackoverflow.com/questions/5301019/what-is-the-difference-between-import-and-include-in-c

Sylvain Defresne writes:
"It is best to avoid #import (sadly) if you want to write
code portable to multiple compilers."

Notice the "sadly". He acknowledges it's helpful, but that
portability considerations limit it's usefulness. And Intel's
ICC, for example, doesn't support #import. But who cares?

I don't have Gcc 9 installed. Maybe someone with Gcc 9
could tell if #import support has been preserved.

David Brown

unread,
Dec 7, 2018, 2:08:25 AM12/7/18
to
Stack Overflow can be a useful source of help and information, but
quoting some random person does not have the level of authority you are
implying here. Nobody is going to be influenced by this person's
feelings about #import.

> And Intel's
> ICC, for example, doesn't support #import. But who cares?
>
> I don't have Gcc 9 installed. Maybe someone with Gcc 9
> could tell if #import support has been preserved.
>

It is highly unlikely to be removed - simply because no one would
prioritise making the change. That does not mean it is a good idea to
use it.

Juha Nieminen

unread,
Dec 7, 2018, 6:35:00 AM12/7/18
to
woodb...@gmail.com wrote:
> I added -Wno-deprecated to get a warning to turn off.

I think that you should only turn off that one particular warning
(IIRC gcc supports turning off individual warnings), rather than
*all* warnings of that type. Else you may be missing some other,
more important warnings.

Juha Nieminen

unread,
Dec 7, 2018, 6:39:08 AM12/7/18
to
David Brown <david...@hesbynett.no> wrote:
> Yes, #import is pointless. It does nothing that you can't do with
> include guards. The time saving from #import compared to include guards
> is /tiny/ - and if you have a decent OS and a decent compiler, /really/
> tiny.

Clearly you haven't been using for extensive periods of time.

You could write that exact same paragraph for tons of other things
(such as range-bosed for loops, for instance). That doesn't mean
those things aren't handy.

It's the small things that reduce boilerplate that make programming
more comfortable.

David Brown

unread,
Dec 7, 2018, 9:02:52 AM12/7/18
to
On 07/12/18 12:38, Juha Nieminen wrote:
> David Brown <david...@hesbynett.no> wrote:
>> Yes, #import is pointless. It does nothing that you can't do with
>> include guards. The time saving from #import compared to include guards
>> is /tiny/ - and if you have a decent OS and a decent compiler, /really/
>> tiny.
>
> Clearly you haven't been using for extensive periods of time.
>

Correct. I have not used #import.

> You could write that exact same paragraph for tons of other things
> (such as range-bosed for loops, for instance). That doesn't mean
> those things aren't handy.
>
> It's the small things that reduce boilerplate that make programming
> more comfortable.
>

I agree that the small things are vital. I don't agree that #import is
such a useful small thing.

Good compilers will handle include guards as fast as #import. And
include guards are standard, will work correctly in awkward cases (such
as accessing the same file from different filesystem paths), will work
correctly no matter how the file is included (even if someone uses
#import), and make it clear in the header file that this is a once-only
include.

So for safe and portable code, you want include guards anyway - and then
#import gives you no benefits. Using #import just gives you bad habits
as you have to change methods when writing code that other people or
other compilers will see.

(Once we get proper modules in C++, and a proper "import" mechanism, it
will be a different matter.)


woodb...@gmail.com

unread,
Dec 7, 2018, 1:41:59 PM12/7/18
to
On Friday, December 7, 2018 at 5:35:00 AM UTC-6, Juha Nieminen wrote:
> woodb...@gmail.com wrote:
> > I added -Wno-deprecated to get a warning to turn off.
>
> I think that you should only turn off that one particular warning
> (IIRC gcc supports turning off individual warnings), rather than
> *all* warnings of that type. Else you maFy be missing some other,
> more important warnings.

Wno-deprecated is the only way I know of to turn it
off. I tried -Wno-import but that didn't turn it off.

Scott Lurndal

unread,
Dec 7, 2018, 2:12:28 PM12/7/18
to
#pragma GCC diagnostic push
#pragma GCC diagnostic warning -Wno-deprecated
#import "xyz.h" /* Shouldn't be using #import anyway */
#pragma GCC diagnostic pop

woodb...@gmail.com

unread,
Dec 7, 2018, 2:15:08 PM12/7/18
to
On Friday, December 7, 2018 at 8:02:52 AM UTC-6, David Brown wrote:
> On 07/12/18 12:38, Juha Nieminen wrote:
> > David Brown <david...@hesbynett.no> wrote:
> >> Yes, #import is pointless. It does nothing that you can't do with
> >> include guards. The time saving from #import compared to include guards
> >> is /tiny/ - and if you have a decent OS and a decent compiler, /really/
> >> tiny.
> >
> > Clearly you haven't been using for extensive periods of time.
> >
>
> Correct. I have not used #import.
>
> > You could write that exact same paragraph for tons of other things
> > (such as range-bosed for loops, for instance). That doesn't mean
> > those things aren't handy.
> >
> > It's the small things that reduce boilerplate that make programming
> > more comfortable.
> >
>
> I agree that the small things are vital. I don't agree that #import is
> such a useful small thing.
>
> Good compilers will handle include guards as fast as #import. And
> include guards are standard, will work correctly in awkward cases (such
> as accessing the same file from different filesystem paths), will work
> correctly no matter how the file is included (even if someone uses
> #import), and make it clear in the header file that this is a once-only
> include.

If you need to do something like that, then use
#includes. You can mix #import and #include.

>
> So for safe and portable code, you want include guards anyway - and then
> #import gives you no benefits.

No one is advocating for #import for portable code.

> Using #import just gives you bad habits
> as you have to change methods when writing code that other people or
> other compilers will see.

"There are rules behind the rules and a unity that is
deeper than uniformity." C.S. Lewis

It seems there is some envy of the freedoms that are
afforded closed-source developers.


Brian
Ebenezer Enterprises
https://github.com/Ebenezer-group/onwards

David Brown

unread,
Dec 7, 2018, 2:39:25 PM12/7/18
to
Your imagination knows no bounds. I write almost exclusively closed
source software. It rarely has to be portable, and I regularly use
compiler extensions or compiler-specific features. That does not mean I
would use a pointless extension which adds nothing to the functionality,
efficiency, elegance, legibility, or correctness of code.

You seem to be basing your use of #import on "I /can/ use it, therefore
I /will/ use it", without the slightest indication of any benefit.

That, of course, is your own choice for your own code. But please stop
pretending that you have discovered something marvellous that you alone
can use to make better code than anyone else.


Scott Lurndal

unread,
Dec 7, 2018, 3:06:58 PM12/7/18
to
I'm sorry, but you're wrong. There's no envy involved at all.

I primarily work on closed source, and we'd _NEVER_ use a
known deprecated feature. It would be pretty stupid to
do that and find in a year or two that everything is broken
because deprecated feature was removed in the next release
of the compiler.

David Brown

unread,
Dec 8, 2018, 8:24:31 AM12/8/18
to
Most of my code is project specific, and keeps the same version of the
same compiler throughout its lifetime. So I /could/ use deprecated
features like this. However, I would only do so if it were particularly
useful - which #import is not.

woodb...@gmail.com

unread,
Dec 8, 2018, 1:51:17 PM12/8/18
to
On Friday, December 7, 2018 at 2:06:58 PM UTC-6, Scott Lurndal wrote:
> woodb...@gmail.com writes:
> >
> >"There are rules behind the rules and a unity that is
> >deeper than uniformity." C.S. Lewis
> >
> >It seems there is some envy of the freedoms that are
> >afforded closed-source developers.
>
> I'm sorry, but you're wrong. There's no envy involved at all.
>
> I primarily work on closed source, and we'd _NEVER_ use a
> known deprecated feature. It would be pretty stupid to
> do that and find in a year or two that everything is broken
> because deprecated feature was removed in the next release
> of the compiler.

As I understand it, support for #import was added, then
deprecated, then undeprecated and then deprecated again.
I'm not sure what to expect regarding #import, but I
wouldn't be surprised if it is reinstated.

David Brown

unread,
Dec 9, 2018, 7:27:21 AM12/9/18
to
I have no idea where you get your information.

#import is a standard directive in Objective-C. At the time gcc
introduced support for Objective-C, they had an attitude of being very
flexible about adding extensions - they added a good many extensions to
C, and supported a range of features from one language or standard
across the other related languages and standards.

Since then, they have realised that this policy was not good in the long
term, and have been far more conservative about adding non-standard
features. The gcc team now prefer to push for getting the features they
want into the C++ (and, to a lesser extent, C) standards.

So #import is deprecated as a poor idea for C and C++. There is /zero/
chance of it ever being undeprecated - no rationale C++ developer would
think it is a good plan to have #import when /real/ modules are on the
horizon as an alternative to #include.


Juha Nieminen

unread,
Dec 9, 2018, 2:05:05 PM12/9/18
to
David Brown <david...@hesbynett.no> wrote:
> And
> include guards are standard, will work correctly in awkward cases (such
> as accessing the same file from different filesystem paths), will work
> correctly no matter how the file is included

Actually no. The "standard" way of using include guards (ie. the
archetypal "#ifdef/#define" at the beginning of the header file,
and the "#endif" at the end) does not guard against recursive
inclusion (file A includes file B, which includes file A. Or even
a longer such chain.)

#pragma once and #import both guard against that.

You can achieve the same effect with even more #defines and #undefs,
but it's even more boilerplate.

David Brown

unread,
Dec 9, 2018, 2:52:15 PM12/9/18
to
File a.h :

#ifndef A_H_
#define A_H_

#include "b.h"
// Defines for A

#endif


File b.h :

#ifndef B_H_
#define B_H_

#include "a.h"
// Defines for B

#endif


If you write #include "a.h" in file C, you will get:


#ifndef A_H_ // True
#define A_H_ // Defines A_H_

#include "b.h" // Includes the following
#ifndef B_H_ // True
#define B_H_ // Defines B_H_

#include "a.h" // Includes the following
#ifndef A_H_ // False
// Skipped
#endif


// Defines for B

#endif

// Defines for A

#endif



You get one set of "Defines for B", and one set of "Defines for A". You
may have to be careful about the ordering of your defines and includes
(if you can't avoid the circular inclusions), but it will work fine.

I have no idea how "#pragma once" and "#import" handle this, but there
is no problem with standard include guards, as far as I can see.

woodb...@gmail.com

unread,
Dec 9, 2018, 11:59:02 PM12/9/18
to
I installed Gcc 9 now and am happy to say that it
still supports #import.

> That does not mean it is a good idea to use it.

"All the world is just a narrow bridge. The most
#important thing is not to be afraid." Rebbe Nachman

David Brown

unread,
Dec 10, 2018, 2:23:06 AM12/10/18
to
That is as expected (do you even /read/ what I write in these posts?) -
and is equally irrelevant.

>
>> That does not mean it is a good idea to use it.
>
> "All the world is just a narrow bridge. The most
> #important thing is not to be afraid." Rebbe Nachman
>

Out-of-context quotations do not justify irrational decisions.

Juha Nieminen

unread,
Dec 10, 2018, 3:04:36 AM12/10/18
to
David Brown <david...@hesbynett.no> wrote:
> You get one set of "Defines for B", and one set of "Defines for A". You
> may have to be careful about the ordering of your defines and includes
> (if you can't avoid the circular inclusions), but it will work fine.

The problem is that, in general, recursive inclusion is an error, and will
usually cause obscure compiler errors that are hard to track. With complex
chains of inclusions it may happen inadvertently.

If a.h includes b.h, and depends on something from the latter, and then
b.h directly or indirectly includes a.h, maybe through a longer chain
of includes, now b.h or something along this chain depends on something
declared in a.h, but the include guard is making everything in a.h to
be skipped, so whatever needs that something from a.h isn't getting it,
and you'll get a compiler error for an undefined name.

If you want a clear error message like "this header file is being
recursively included", you need additional #defines to check for this.

David Brown

unread,
Dec 10, 2018, 5:34:26 AM12/10/18
to
On 10/12/18 09:04, Juha Nieminen wrote:
> David Brown <david...@hesbynett.no> wrote:
>> You get one set of "Defines for B", and one set of "Defines for A". You
>> may have to be careful about the ordering of your defines and includes
>> (if you can't avoid the circular inclusions), but it will work fine.
>
> The problem is that, in general, recursive inclusion is an error, and will
> usually cause obscure compiler errors that are hard to track. With complex
> chains of inclusions it may happen inadvertently.

Yes, recursive inclusion is likely to be a design flaw. And it may
cause odd errors. But I'd be surprised to see it turn up often.

And standard include guards handle it as well as other mechanisms.

>
> If a.h includes b.h, and depends on something from the latter, and then
> b.h directly or indirectly includes a.h, maybe through a longer chain
> of includes, now b.h or something along this chain depends on something
> declared in a.h, but the include guard is making everything in a.h to
> be skipped, so whatever needs that something from a.h isn't getting it,
> and you'll get a compiler error for an undefined name.
>

That is true of any kind of recursive import mechanism.

> If you want a clear error message like "this header file is being
> recursively included", you need additional #defines to check for this.
>

Ah, so what you were saying is that the standard include guards don't
make it easy to spot this kind of recursion and warn you about it.
Neither does gcc #import. But both methods give you the expected results.

Tim Rentsch

unread,
Dec 10, 2018, 7:56:06 AM12/10/18
to
woodb...@gmail.com writes:

> Shalom
>
> One of the comments in this thread:
> https://www.reddit.com/r/cpp/comments/a14o5q/real_world_problems_with_pragma_once/
>
> said that Cray doesn't support pragma once. I know gcc,
> Clang and MSVC do support it. I was wondering if Intel,
> IBM or Oracle compilers support it.
>
> In my software:
>
> I've been using pragma once for a number of years, but
> maybe I should switch to using include guards. In the
> past I had more include files, but now just have a few,
> so switching to include guards would be easy.

To me the (implicit) question here seems like a no-brainer.
It probably cost you more time and effort to do the research
and post here about it than it would have just to change to
using include guards. The main advantage of using include
guards is you know they are going to work and you'll never
have to think about them or wonder if they might be causing
problems. The main advantage of #pragma once is ... what?
Unless there are very particular motivating circumstances,
using #pragma once seems like all potential downside with
negligible upside. Given that the energy barrier to getting
rid of the existing #pragma's is low, just do it and be done
with it. Save your brain for more important matters.

By the way I think the usual #ifndef/#define...#endif style of
include guards is ugly. But they do the job very reliably, so
I just use 'em and move on.

woodb...@gmail.com

unread,
Dec 10, 2018, 1:11:14 PM12/10/18
to
On Monday, December 10, 2018 at 6:56:06 AM UTC-6, Tim Rentsch wrote:
>
> To me the (implicit) question here seems like a no-brainer.
> It probably cost you more time and effort to do the research
> and post here about it than it would have just to change to
> using include guards. The main advantage of using include
> guards is you know they are going to work and you'll never
> have to think about them or wonder if they might be causing
> problems. The main advantage of #pragma once is ... what?

Probably the main advantage of #pragma once is that it's
easier to output for my on-line code generator.

> Unless there are very particular motivating circumstances,
> using #pragma once seems like all potential downside with
> negligible upside. Given that the energy barrier to getting
> rid of the existing #pragma's is low, just do it and be done
> with it. Save your brain for more important matters.

On the other hand, the Cray compiler is the only compiler
I know of that doesn't support #pragma once. I don't hear
much about Cray. If I found someone with that compiler
that was interested in using my software, I'd go ahead
and switch, but I tend to think that individuals and small
companies are most likely to be persuaded by my approach.
What's the smallest company that uses Cray's compiler?
Maybe 20 people? That's a lot bigger company than what
I'm thinking of.

red floyd

unread,
Dec 10, 2018, 1:17:51 PM12/10/18
to
a.h:

#ifndef A_H_
#define A_H_
...
#else
#error A.h has been included multiple times.
#endif

Recursion, on the other hand is more difficult.

#ifdef INCLUDING_A_H_
#error a.h is recursively included
#else
#define INCLUDING_A_H_
#ifndef A_H_
...
#endif /* A_H_ */
#undef INCLUDING_A_H_
#endif /* INCLUDING_A_H_ */


David Brown

unread,
Dec 10, 2018, 3:49:54 PM12/10/18
to
That would be easier written:

#ifdef A_H_
#error A.h has been included multiple times.
#endif
#define A_H_

Then it would not need to be split up at the start and end of the file.

However, it is a terrible idea, IMHO - Like many people, I /want/ to be
able to write #include "a.h" for any headers and any C files that rely
on definitions or declarations from that file. I don't want multiple
inclusion to be an error - I want it to work safely. That's what
standard include guards do.

Juha Nieminen

unread,
Dec 11, 2018, 8:06:19 AM12/11/18
to
David Brown <david...@hesbynett.no> wrote:
> That would be easier written:
>
> #ifdef A_H_
> #error A.h has been included multiple times.
> #endif
> #define A_H_
>
> Then it would not need to be split up at the start and end of the file.
>
> However, it is a terrible idea, IMHO - Like many people, I /want/ to be
> able to write #include "a.h" for any headers and any C files that rely
> on definitions or declarations from that file. I don't want multiple
> inclusion to be an error - I want it to work safely. That's what
> standard include guards do.

Yeah, the proposed solution isn't good for guarding against recursive
inclusion as it stops the same header from being included more than
once (which easily happens, and is not an error nor even bad design).

There is a way to detect recursive inclusion, but you need additional
defines to do that. Something like:

#ifdef A_H_RECURSION_GUARD
#error "a.h is being recursively included"
#endif
#ifndef A_H_
#define A_H_
#define A_H_RECURSION_GUARD

...

#undef A_H_RECURSION_GUARD
#endif

Vir Campestris

unread,
Dec 11, 2018, 4:53:44 PM12/11/18
to
I had a few minutes free today at work, so I hacked a bit of bash
together and ran some benchmarks.

main.c #includes .h files.
i1.h
i2.h
...
i999.h

Most of these have nothing interesting in them.

The first 100 contains statements #including their name with an
additional digit - so i4.h has

#include "i40.h"
#include "i41.h"
...
#include "i49.h"

which of course in turn include the next level.

When I used #ifdef / #define / #endif guards the files are obviously a
fair bit bigger than if I just start them with #pragma once.

Nevertheless the compile speed is about 8 times faster for include
guards vs #pragma.

And yes, I did check the #pragma once was working.

GCC 7.3, Ubuntu 18, Xeon E5-2640 with SSD and 32Gb RAM.

Andy

woodb...@gmail.com

unread,
Dec 11, 2018, 10:06:35 PM12/11/18
to
I've heard that GCC has a performance problem with its
#pragma once implementation. If I remember right, there's
a bug open on the matter for a long time.


>
> Andy

David Brown

unread,
Dec 12, 2018, 3:15:12 AM12/12/18
to
I think it might be better to say that gcc does not need a non-standard
pragma to efficiently handle multiply included files, because it has
highly efficient handling of the standard include guards. There may be
other compilers - like MSVC - that don't have such efficient handling of
include guards, and which then benefit from non-standard additions like
#pragma once.

But you are using gcc for your internal code. And you are generating
standard code for other compilers. It seems obvious to me that you
should be using standard include guards in both cases, and can drop all
thoughts of non-standard solutions (#pragma once, #import). They are
always unnecessary, not always supported, and give no compile speed
benefits. It's a no-brainer, except perhaps for people working
specifically on MSVC code.


Alf P. Steinbach

unread,
Dec 12, 2018, 5:44:56 AM12/12/18
to
On 12.12.2018 09:15, David Brown wrote:
> [snip]
> But you are using gcc for your internal code. And you are generating
> standard code for other compilers. It seems obvious to me that you
> should be using standard include guards in both cases, and can drop all
> thoughts of non-standard solutions (#pragma once, #import). They are
> always unnecessary, not always supported, and give no compile speed
> benefits. It's a no-brainer, except perhaps for people working
> specifically on MSVC code.

Focusing on build efficiency with a given compiler is IMHO the entirely
wrong thing to do, a not smart thing to do.

I would recommend to focus primarily on /correctness/. And secondarily
on productivity, e.g. time wasted on checking uniqueness of new include
guard names; time wasted on realizing that a copied include guard was
the cause of errors; reduced motivation and joy due to grappling with
too archaic technology (include guards)... I believe that these costs
far outweigh the costs of build times with a given compiler.

In the Reddit thread cited by Brian in original posting, no-one reported
any problems with using `#pragma once`. Several people reported problems
with classical include guards.


Cheers!

- Alf

Bo Persson

unread,
Dec 12, 2018, 7:37:01 AM12/12/18
to
This might have been true once, but MSVC fixed the include guard
handling more than 5 years ago. Now there is no difference.


Bo Persson



David Brown

unread,
Dec 12, 2018, 8:32:41 AM12/12/18
to
On 12/12/18 11:44, Alf P. Steinbach wrote:
> On 12.12.2018 09:15, David Brown wrote:
>> [snip]
>> But you are using gcc for your internal code. And you are generating
>> standard code for other compilers. It seems obvious to me that you
>> should be using standard include guards in both cases, and can drop all
>> thoughts of non-standard solutions (#pragma once, #import). They are
>> always unnecessary, not always supported, and give no compile speed
>> benefits. It's a no-brainer, except perhaps for people working
>> specifically on MSVC code.
>
> Focusing on build efficiency with a given compiler is IMHO the entirely
> wrong thing to do, a not smart thing to do.
>

It makes sense - /if/ it is the compiler you are using for development,
and the project is big enough that compile time has become an issue, and
you have exhausted other more effective ways of improving build times
(decent build manager, parallel builds, ccache, etc.). This does not
sound like the case for the OP. So the sensible solution is to stick to
the standard method - and as a bonus, this is highly efficient with his
choice of tools.

> I would recommend to focus primarily on /correctness/. And secondarily
> on productivity, e.g. time wasted on checking uniqueness of new include
> guard names; time wasted on realizing that a copied include guard was
> the cause of errors; reduced motivation and joy due to grappling with
> too archaic technology (include guards)... I believe that these costs
> far outweigh the costs of build times with a given compiler.
>

Yes, those are all much more important than the build times.

> In the Reddit thread cited by Brian in original posting, no-one reported
> any problems with using `#pragma once`. Several people reported problems
> with classical include guards.
>

I haven't looked at the thread. I can't say I have ever had problems
with include guards - certainly no problems that were not part of a
bigger issue (such as a project having more than one include file of the
same name, from different directories).


David Brown

unread,
Dec 12, 2018, 8:34:35 AM12/12/18
to
Great - one less reason to use anything other than include guards.

(I don't use MSVC myself, and don't keep up with all its changes, so it
is good to be updated.)



Scott Lurndal

unread,
Dec 12, 2018, 9:08:18 AM12/12/18
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>On 12.12.2018 09:15, David Brown wrote:
>> [snip]

>In the Reddit thread cited by Brian in original posting, no-one reported
>any problems with using `#pragma once`. Several people reported problems
>with classical include guards.

Which means little to nothing. A small handful of people use #pragma once,
while millions use classic include guards.

woodb...@gmail.com

unread,
Dec 12, 2018, 2:31:31 PM12/12/18
to
I think more people would use #pragma once if Gcc
improved the performance of their implementation of it.

Jorgen Grahn

unread,
Dec 12, 2018, 6:58:22 PM12/12/18
to
On Wed, 2018-12-12, David Brown wrote:
> On 12/12/18 11:44, Alf P. Steinbach wrote:
...

>> In the Reddit thread cited by Brian in original posting, no-one reported
>> any problems with using `#pragma once`. Several people reported problems
>> with classical include guards.
>>
>
> I haven't looked at the thread. I can't say I have ever had problems
> with include guards - certainly no problems that were not part of a
> bigger issue (such as a project having more than one include file of the
> same name, from different directories).

IMO, same include file name in different directories is a good policy.
protocols/foo/encoder.h is a better name than
prococols/foo/foo_protocol_encoder.h.

But include guards should be named after more than just the file name.
If someone on the project has bad habits in that respect (a quick grep
will tell) it's time to educate him/her. It's also easy in most cases
to add a build step which fails the build on duplicate guards.

I can't remember when I've had issues with this, but it probably
happened once or twice over the years. I.e., an unsignificant problem
from my point of view. I probably wasted more time reading this
thread.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Vir Campestris

unread,
Dec 13, 2018, 4:11:03 PM12/13/18
to
On 12/12/2018 12:36, Bo Persson wrote:
> This might have been true once, but MSVC fixed the include guard
> handling more than 5 years ago. Now there is no difference.

Upthread I mentioned benchmarking MSVC. It was more than 5 years ago. A
_lot_ more.

I don't have access to a recent model MSVC.

Andy
0 new messages