Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: .h Files and forward Declarations  (Read 24525 times)

0 Members and 1 Guest are viewing this topic.

l0calh05t

  • Full Member
  • ***
  • Posts: 200
    • View Profile
.h Files and forward Declarations
« Reply #15 on: February 20, 2011, 10:11:30 pm »
Quote from: "devlin"
Quote from: "Saboba42"
Ok, so I am gathering that #pragma once is out as a solution.

... because?

I'm only using pragma once (without include guards - I haven't used them for several years after getting bit by the same-name "feature" once) and compiling projects happily on windows, linux and mac os x.


You really shouldn't use only pragma once. It is a nonstandard extension, so if anything use it in addition to include guards to speed up compilation on compilers that support it.

PS: About the "limiting to one compiler" argument: even in that case, I wouldn't use only pragma once, because you risk getting into a "bad habit" which might come back to bite you when you do need to write a portable piece of software.

One solution to the whole "same name" problem (which can also occur with namespaces!) is to use a (probably) unique identifier, like a 128 bit hash (as hex prepended with a letter to create a valid identifier or some other format) of your name and the name you actually want to use.

In the namespace case renaming is then as simple as writing namespace <new> = <old>; (only in source files though, of course). In the includeguard case, no renaming is needed really. And if you have the odd macro... well... it gets a little ugly. but macros are always ugly.

Silvah

  • Guest
.h Files and forward Declarations
« Reply #16 on: February 21, 2011, 06:48:48 pm »
Let's play a devil's advocate! :D
Quote from: "l0calh05t"
It is a nonstandard extension
Strictly speaking, it's not. Nonstandard extension are the things that are ill-formed according to the standard, but the implementation allows them. #pragma directives are implementation-defined, not ill-formed. Thus, they're not extensions.

Quote from: "l0calh05t"
PS: About the "limiting to one compiler" argument
It's "limiting to all but the most obscure compilers". #pragma once is very widely implemented, I've heard of one (yes, one!) compiler that doesn't support it (I think there are more compilers don't supporting this #pragma, but they're so obscure that chances are nobody of us will use them anyway).

Quote from: "l0calh05t"
One solution to the whole "same name" problem (which can also occur with namespaces!) is to use a (probably) unique identifier, like a 128 bit hash (as hex prepended with a letter to create a valid identifier or some other format) of your name and the name you actually want to use.
In order to avoid name clashes, you suggest using identifiers that are still non-unique, but additionally unwieldy long and horribly ugly. Oh well...

l0calh05t

  • Full Member
  • ***
  • Posts: 200
    • View Profile
.h Files and forward Declarations
« Reply #17 on: February 21, 2011, 07:07:10 pm »
Quote from: "Silvah"
Quote from: "l0calh05t"
One solution to the whole "same name" problem (which can also occur with namespaces!) is to use a (probably) unique identifier, like a 128 bit hash (as hex prepended with a letter to create a valid identifier or some other format) of your name and the name you actually want to use.
In order to avoid name clashes, you suggest using identifiers that are still non-unique, but additionally unwieldy long and horribly ugly. Oh well...


They aren't that long really. And it only needs to be applied to the top level namespace. And they much, much, much more likely to be unique than any word or readable acronym. So it is definitely an improvement.

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
.h Files and forward Declarations
« Reply #18 on: February 21, 2011, 07:39:11 pm »
To be honest - I won't end up in a bad habit - having used inclusion guards for years during development for multiple simultaneous platforms, including PS2 and Xbox.

The fact is that pragma once is (very) convenient, and while all my current platforms (windows, macosx and linux) have compilers that support it - if I ever come across a platform that doesn't (yet supports c++) - it's nothing a quick perl-script can't handle.

Each to his own, but the arguments against pragma once are mostly archaic. Surprised you didn't bring up actual pitfalls like erroneous symlink-handling though (although I believe it's just LCC having that problem) :)

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
.h Files and forward Declarations
« Reply #19 on: February 21, 2011, 09:28:31 pm »
Quote from: "Silvah"
#pragma directives are implementation-defined, not ill-formed. Thus, they're not extensions.
The #pragma directive itself isn't the problem, that's why you can use both #pragma once and header guards in portable code. However, abandoning header guards may render code ill-formed on a standard-compliant compiler.

I think #pragma once is okay for own projects that only have to work on a few compilers. But when you develop an open-source library that ought to be portable, you should use normal header guards (maybe in addition to #pragma once).
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Silvah

  • Guest
.h Files and forward Declarations
« Reply #20 on: February 21, 2011, 10:20:02 pm »
Quote from: "devlin"
Surprised you didn't bring up actual pitfalls like erroneous symlink-handling though (although I believe it's just LCC having that problem)
If the compiler tries to be smart, the same thing can happen with normal include guards, it doesn't apply exclusively to #pragma once.
Quote from: "Nexus"
However, abandoning header guards may render code ill-formed on a standard-compliant compiler.
I think you missed the point slightly, I just said that #pragmas aren't extensions, I didn't said anything about what might happen if a compiler doesn't support the #pragma we're talking about. So, the quote isn't really appropriate here.

You're right, of course. The lack of #pragma once support certainly may render otherwise valid code ill-formed. But how many compilers don't supporting that are you aware of? #pragma once is available on almost all compilers. If it isn't, then probably it's just one of the many things you'll have problems with.

Well, I'm still playing a devil's advocate, I actually agree that in truly portable code normal header guards should be used.

Saboba42

  • Newbie
  • *
  • Posts: 8
    • View Profile
.h Files and forward Declarations
« Reply #21 on: February 22, 2011, 06:09:11 am »
*cough*

While the merits or non-merits of #pragma once are fascinating, I have already attempted to use the command with my version of Code::Blocks and noticed no noticeable change.  I then decided to attempt removing the #defif header guards, which caused "multiple include" errors, showing me that it is unlikely that my version of the gcc compiler likes #pragma once, and in either case it has not fixed the problem.

Are there any other ides as to the cause of my problem?  Like I said, I am writing the problematic files in the exact same format used by the rest of the engine.  The rest of the engine works fine, and the example code seems to compile fine on other peoples' compilers, but my compiler still gives me errors which tell me the compiler recognizes that I forward-declared an object in a header, but when I try to use that object in another header with the #include command, it still tells me <object name> has no type as if it were not declared.

*steals the above discussion for a small introductory pamphlet on #pragma once and uses the proceeds to hire a 3rd or 4th rate debugging specialist*

DoctorJ

  • Newbie
  • *
  • Posts: 21
    • View Profile
.h Files and forward Declarations
« Reply #22 on: February 22, 2011, 06:34:14 am »
For the sake of testing, can you move or copy that "enum MakeEvent ..." into EventManager.h and confirm that everything would work if it could find it? Perhaps add a fake enum into GQE_Types.h and see if it that can be referenced somewhere else within EventManager.h?

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
.h Files and forward Declarations
« Reply #23 on: February 22, 2011, 08:40:22 am »
Sorry Saboba. :)

Just a few thoughts:
Code: [Select]
const MakeEvent theEvent

Did you intend to make it a const reference? (and thus forgot the &)

Also, namespaces shouldn't have a semicolon ';' after them. Usually this isn't much of an issue as it would be stripped out by the compiler as a noop - but I'm not sure how well C::B functions.

Silvah

  • Guest
.h Files and forward Declarations
« Reply #24 on: February 22, 2011, 09:26:25 am »
Quote from: "Saboba42"
I then decided to attempt removing the #defif header guards, which caused "multiple include" errors, showing me that it is unlikely that my version of the gcc compiler likes #pragma once
GCC supports #pragma once since 2.95, I think. It was released in 1999. Now we have 2011, GCC 4.6.0 will be released soon. It's update time!

But... thank you for proving that I was wrong: not only very obscure compilers don't support it. Severely outdated ones don't, either.

l0calh05t

  • Full Member
  • ***
  • Posts: 200
    • View Profile
.h Files and forward Declarations
« Reply #25 on: February 22, 2011, 05:38:08 pm »
Quote from: "Silvah"

But... thank you for proving that I was wrong: not only very obscure compilers don't support it. Severely outdated ones don't, either.


You are wrong again, as some versions of GCC didn't/still do not support pragma once (like mingw, not sure if that's still true, but it was for a long time)

And in fact it was declared deprecated after a few versions in GCC. soo.. yeah. avoid it, imo...

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
.h Files and forward Declarations
« Reply #26 on: February 22, 2011, 05:47:27 pm »
Quote from: "l0calh05t"
And in fact it was declared deprecated after a few versions in GCC. soo.. yeah. avoid it, imo...

Now you're just grasping at straws :)

Quote
However, with the 3.4 release of GCC, the #pragma once handling code was fixed to behave correctly with symbolic and hard links. The feature was "un-deprecated" and the warning removed.

l0calh05t

  • Full Member
  • ***
  • Posts: 200
    • View Profile
.h Files and forward Declarations
« Reply #27 on: February 22, 2011, 05:52:45 pm »
Quote from: "devlin"
Quote from: "l0calh05t"
And in fact it was declared deprecated after a few versions in GCC. soo.. yeah. avoid it, imo...

Now you're just grasping at straws :)

Quote
However, with the 3.4 release of GCC, the #pragma once handling code was fixed to behave correctly with symbolic and hard links. The feature was "un-deprecated" and the warning removed.


So? It was still deprecated for a few versions. Just pointing out that such extensions cannot be relied on.

Silvah

  • Guest
.h Files and forward Declarations
« Reply #28 on: February 22, 2011, 06:38:37 pm »
Quote from: "l0calh05t"
some versions of GCC didn't/still do not support pragma once (like mingw, not sure if that's still true, but it was for a long time)
[citation needed]

Quote from: "l0calh05t"
it was declared deprecated after a few versions in GCC
It was. It's not since GCC 3.4.0, which was released in 2004.

Quote from: "l0calh05t"
Just pointing out that such extensions cannot be relied on.
#pragmas are not extensions. Read my post again.

l0calh05t

  • Full Member
  • ***
  • Posts: 200
    • View Profile
.h Files and forward Declarations
« Reply #29 on: February 22, 2011, 07:00:49 pm »
Quote from: "Silvah"
It was. It's not since GCC 3.4.0, which was released in 2004.

I said was. ;)

Quote
#pragmas are not extensions. Read my post again.


"#pragma" in and of itself is not an extension, but "#pragma once" is not part of any C or C++ standard. #pragma is specifically designed for compiler/os specific options and therefore non-portable.

About mingw: The current version is ok with pragma once, although I did find a pragma once related bug in it's tracker (for the current version)