Include guards and inclusion order

J

Johannes Bauer

Hello group,

there are these moments when I just hate C++. This is one of them.

So, I've been working on this project for a long time, classes have
grown and become quite many, now it's time for the "inclusion fiasco".

I've used include guards to protect my header files and always included
the necessary includes so my include files are parsed correctly. I.e. I
have constructs like

Vehicle.hpp:

#ifndef VEHICLE_HPP
#define VEHICLE_HPP

#include <SDL.h>

#include "Sound.hpp"
#include "Map.hpp"
#include "SpriteManager.hpp"

class Vehicle {
[...]
};

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

.../include/Vehicle.hpp:40: error: ‘SpriteIDType’ in class
‘SpriteManager’ does not name a type

Well - yes it does. SpriteManager::SpriteIDType is a enum defined in
SpriteManager.hpp. However I don't really grasp anymore why it is or
isn't included. I'm pretty desperate now since I've tried a whole day to
insert forward declaraions at the necessary places and nothing worked.

Should I always prefer to use forward declarations if possible instead
of including whole header files? Should I use include guards?

How can I solve this mess? How can I force g++ to print me in which
order it has included which files (as this is pretty hard to track down,
it always just shows the last one)?

TIA,
Johannes
 
R

robertwessel2

Hello group,

there are these moments when I just hate C++. This is one of them.

So, I've been working on this project for a long time, classes have
grown and become quite many, now it's time for the "inclusion fiasco".

I've used include guards to protect my header files and always included
the necessary includes so my include files are parsed correctly. I.e. I
have constructs like

Vehicle.hpp:

#ifndef VEHICLE_HPP
#define VEHICLE_HPP

#include <SDL.h>

#include "Sound.hpp"
#include "Map.hpp"
#include "SpriteManager.hpp"

class Vehicle {
[...]

};

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

../include/Vehicle.hpp:40: error: 'SpriteIDType' in class
'SpriteManager' does not name a type

Well - yes it does. SpriteManager::SpriteIDType is a enum defined in
SpriteManager.hpp. However I don't really grasp anymore why it is or
isn't included. I'm pretty desperate now since I've tried a whole day to
insert forward declaraions at the necessary places and nothing worked.

Should I always prefer to use forward declarations if possible instead
of including whole header files? Should I use include guards?

How can I solve this mess? How can I force g++ to print me in which
order it has included which files (as this is pretty hard to track down,
it always just shows the last one)?


While somewhat OT, GCC, and most other C and C++ compilers, can output
the source file after preprocessing is completed, which should let you
see what's actually been included. With GCC the option is likely "-E".
 
J

Johannes Bauer

While somewhat OT, GCC, and most other C and C++ compilers, can output
the source file after preprocessing is completed, which should let you
see what's actually been included. With GCC the option is likely "-E".

Yes it does - I've already looked into that. Results in a 1.5 MB large
file which is mostly STL. Probably useful if you could read it properly
- I can't, however :-/

Greetings,
Johannes
 
L

LR

Johannes said:
Hello group,
Hi.


there are these moments when I just hate C++. This is one of them.

So, I've been working on this project for a long time, classes have
grown and become quite many, now it's time for the "inclusion fiasco".

I've used include guards to protect my header files and always included
the necessary includes so my include files are parsed correctly. I.e. I
have constructs like

Vehicle.hpp:

#ifndef VEHICLE_HPP
#define VEHICLE_HPP

#include <SDL.h>

#include "Sound.hpp"
#include "Map.hpp"
#include "SpriteManager.hpp"

class Vehicle {
[...]
};

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

../include/Vehicle.hpp:40: error: ‘SpriteIDType’ in class
‘SpriteManager’ does not name a type

Well - yes it does. SpriteManager::SpriteIDType is a enum defined in
SpriteManager.hpp. However I don't really grasp anymore why it is or
isn't included.

I'm not sure about anyone else, but I can't tell either from the code
you posted. May I suggest that you post the smallest possible example
of this not working. I often find that trying this shows me the path to
a solution.
> I'm pretty desperate now since I've tried a whole day to
insert forward declaraions at the necessary places and nothing worked.


Should I always prefer to use forward declarations if possible instead
of including whole header files?

Always? No. Sometimes? Yes. When? More complicated.
Should I use include guards?

Almost always. There are a few situations where it wouldn't be what you
wanted. The ones I can think of off hand are things that probably
shouldn't be done anyway.

How can I solve this mess?

I don't think I can tell yet. I can't see the code that is causing the
trouble.

LR
 
D

Daniel T.

Johannes Bauer said:
I've used include guards to protect my header files and always included
the necessary includes so my include files are parsed correctly. I.e. I
have constructs like

Vehicle.hpp:

#ifndef VEHICLE_HPP
#define VEHICLE_HPP

#include <SDL.h>

#include "Sound.hpp"
#include "Map.hpp"
#include "SpriteManager.hpp"

class Vehicle {
[...]
};

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

../include/Vehicle.hpp:40: error: ŒSpriteIDType¹ in class
ŒSpriteManager¹ does not name a type

Well - yes it does. SpriteManager::SpriteIDType is a enum defined in
SpriteManager.hpp. However I don't really grasp anymore why it is or
isn't included. I'm pretty desperate now since I've tried a whole day to
insert forward declaraions at the necessary places and nothing worked.

Should I always prefer to use forward declarations if possible instead
of including whole header files? Should I use include guards?
How can I solve this mess?

IMHO, you should prefer #including header files, but this is a minority
opinion. One reason I hold to this view is because It helps point out
flawed designs such as this. You have three classes that each depend on
both of the others, but they are all in separate file sets as if they
were independent. They aren't.

Create a single .h and .cpp file that contains GameState, Vehicle and
SurfaceManager because they are all mutually dependent. Then look at
your design and see how you can break them up if time permits.
 
P

Paul Sinnett

Johannes said:
Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

.../include/Vehicle.hpp:40: error: 'SpriteIDType' in class
'SpriteManager' does not name a type

If you follow it step by step from the cpp file that was being
compiled you'll probably see what's going wrong. I'm guessing it goes
something like:

->#include "SpriteManager.hpp"

which opens SpriteManager.hpp

->#ifndef SPRITE_MANAGER_HPP

this will be true since nothing else has been defined yet

->#define SPRITE_MANAGER_HPP

->#include "Vehicle.hpp"

which opens Vehicle.hpp

->#ifndef VEHICLE_HPP

also true at this point

->#define VEHICLE_HPP

->#include "SpriteManager.hpp"

which opens SpriteManager.hpp for the second time

->#ifndef SPRITE_MANAGER_HPP

this is now false since it's the second time we've opened this file
and we haven't finished processing the header, if the rest of
Vehicle.hpp is relying on something defined in SpriteManager.hpp then
it's not going to get it because the include guard is going to skip
it.
 
J

Jim Langston

Johannes Bauer said:
Hello group,

there are these moments when I just hate C++. This is one of them.

So, I've been working on this project for a long time, classes have
grown and become quite many, now it's time for the "inclusion fiasco".

I've used include guards to protect my header files and always included
the necessary includes so my include files are parsed correctly. I.e. I
have constructs like

Vehicle.hpp:

#ifndef VEHICLE_HPP
#define VEHICLE_HPP

#include <SDL.h>

#include "Sound.hpp"
#include "Map.hpp"
#include "SpriteManager.hpp"

class Vehicle {
[...]
};

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

This can be the source of your problem. If header A needs header B and
header B needs header A there is no way to resolve it without restructuring.
If you are using pointers then a forward declaration might solve it for you.
../include/Vehicle.hpp:40: error: 'SpriteIDType' in class
'SpriteManager' does not name a type

Well - yes it does. SpriteManager::SpriteIDType is a enum defined in
SpriteManager.hpp. However I don't really grasp anymore why it is or
isn't included. I'm pretty desperate now since I've tried a whole day to
insert forward declaraions at the necessary places and nothing worked.

Hmm.. are you positive you don't need to resolve the enum?
someclass::SpriteIDType or something?
Should I always prefer to use forward declarations if possible instead
of including whole header files? Should I use include guards?

Definately to the secnod, always use include guards.
The first question can be tricky. Generally with headers including headers
and such and proper use of include guards, the header will only be included
once in each compilation unit. There may be cases where you need a forward
declaration, but that usually only helps when you are dealing with pointers
and don't need to see the internals of a class.
How can I solve this mess? How can I force g++ to print me in which
order it has included which files (as this is pretty hard to track down,
it always just shows the last one)?

It's hard to say without seeing code.
 
J

jarl.lindrud

Now at some point I get a cycle of three classes GameState, Vehicle and
SurfaceManager which all require one of the others. The compiler just
frenzies:

It sounds like you are including class headers when a forward
declaration would suffice.

In all probability, one of the classes in the cycle only needs a
forward declaration of the others, and then the problem is solved, by
putting that class in its own header together with the forward
declarations it needs.

Just remember that if all the compiler has seen of a class X is a
forward declaration, then the interface and the members of the class
you're defining will only be able to use types X& or X*, not X.

Jarl.
 
A

Alf P. Steinbach

* (e-mail address removed):
Just remember that if all the compiler has seen of a class X is a
forward declaration, then the interface and the members of the class
you're defining will only be able to use types X& or X*, not X.

I'm sorry, with a natural interpretation of "use" in this context, that
is incorrect.

For example, you can declare a function that returns X or takes an X
argument by value.

However, there are of course restrictions on incomplete types. For
example, you cannot instantiate an X or call any member functions on an
X. In short, you cannot do anything that requires knowledge of the
details of X, including its size.

Cheers, & hth.

- Alf
 
J

Juha Nieminen

Include guards are more or less mandatory so you shouldn't drop those.
(I don't really understand why the C++ standard can't simply state that
if a file is included more than once, only the first inclusion is taken
into account; I can't think of any use for multiple inclusion of the
same file in such way that its contents is parsed for each inclusion,
bar some really ugly obfuscated preprocessor trickery which nobody
really needs anyways.)

It's actually a good idea to always minimize the number of #include
lines in headers, especially #includes which refer to headers in the
same project. (Standard includes are exempt from this principle because
they don't present any problem and they don't change during
development). One advantage of this is that it will reduce the amount of
dependency between files, making compilation faster (ie. modifying 1
header file is less likely to cause the entire project to be
recompiled). And of course using this principle lessens the probability
of recursive inclusion.

If a class only uses references/pointers to some other class in its
declaration, there's no need to #include the declaration of that other
class. Just pre-declare it. You will make compilation faster and reduce
the risk of recursive inclusion.
Even if two (or more) classes must see each other, you can still get
away with pre-declaration of at least one of the classes in the header
of the other class (because it's impossible to have an instance of the
other class as member variable in both classes).

One rare case where seeing the declaration of the other class can be
mandatory is if that other class defines some types or constants (such
as enums) inside itself and these are used in the declaration of the
other class, and this also happens vice-versa. In this case both classes
would need to see the declaration of the other class, which could cause
a problem.

Depending on the actual case, this kind of inter-dependency may
actually be bad OO design, and it would benefit from a better re-design.
If this is not an option, then the only solution is to take the
types/enums/whatever out of at least one of the classes and put them in
their own header file (usually inside a namespace).

Catching the exact place where recursive inclusion happens can be a
bit difficult because recursive inclusion usually causes extremely weird
compiler errors which can happen at places which have nothing to do with
the actual problem. There is, however, a preprocessor trick which can be
used to catch them. The trick is to consistently do this alongside the
inclusion guards:

// Header file begin
#ifdef THIS_CLASS_RECURSION_GUARD
#error Recursive include
#endif
#ifndef THIS_CLASS_INCLUSION_GUARD
#define THIS_CLASS_INCLUSION_GUARD
#define THIS_CLASS_RECURSION_GUARD

// All of the contents of the header file here...

#undef THIS_CLASS_RECURSION_GUARD
#endif
// Header file end
 
D

David Harmon

On Sat, 01 Dec 2007 21:30:34 +0100 in comp.lang.c++, Johannes Bauer
Should I always prefer to use forward declarations if possible instead
of including whole header files? Should I use include guards?

Yes and yes. And each header should ordinarily include any headers
it depends upon, relying on include guards to prevent duplication.
And each header should be able to be included in any order, or by
itself. When possible.

// File: a.hpp
#ifndef inc_a_hpp
#define inc_a_hpp

class B;

class A {
B* ptr;
B* foo();
};

#include "b.hpp"

B* A::foo()
{
ptr = new B;
return ptr;
}

#endif
// End of a.hpp



// File: b.hpp
#ifndef inc_b_hpp
#define inc_b_hpp

class A;

class B {
A* ptr;
A* foo();
};

#include "a.hpp"

A* B::foo()
{
ptr = new A;
return ptr;
}

#endif
// End of b.hpp
 
J

James Kanze

(e-mail address removed) schrieb:
Yes it does - I've already looked into that. Results in a 1.5 MB large
file which is mostly STL. Probably useful if you could read it properly
- I can't, however :-/

That sounds like a problem with your tool set. Open it in your
editor, and search for symbols in question.

Not that it's really necessary here. It seems rather obvious
that you've got a cyclic dependency in your headers. You'll
have to break it somehow.

With good design, of course, it wouldn't be there to begin with,
so the correct solution is to go back and correct the design,
then recode. It will cost you a lot less time in the long run,
and possibly even in the short run as well.
 
P

Pete Becker

Include guards are more or less mandatory so you shouldn't drop those.
(I don't really understand why the C++ standard can't simply state that
if a file is included more than once, only the first inclusion is taken
into account; I can't think of any use for multiple inclusion of the
same file in such way that its contents is parsed for each inclusion,
bar some really ugly obfuscated preprocessor trickery which nobody
really needs anyways.)

Read about <assert.h>.
 
J

Juha Nieminen

Pete said:
Read about <assert.h>.

I did, and I still can't understand why including <assert.h> several
times would make a difference.

And anyways, even if it did make a difference, wouldn't it be better
to simply have some kind of #pragma or whatever which tells the compiler
"it's ok to include this file more than once", the default behavior
being, when that #pragma does not appear, that multiple inclusions are
ignored?
 
D

David Harmon

On Mon, 03 Dec 2007 01:43:35 +0200 in comp.lang.c++, Juha Nieminen
I did, and I still can't understand why including <assert.h> several
times would make a difference.

If you change the definition of #define NDEBUG and include it again,
you get a different assert() macro for that part of the source.
 
P

peter koch

I did, and I still can't understand why including <assert.h> several
times would make a difference.

And anyways, even if it did make a difference, wouldn't it be better
to simply have some kind of #pragma or whatever which tells the compiler
"it's ok to include this file more than once", the default behavior
being, when that #pragma does not appear, that multiple inclusions are
ignored?

I believe that what Pete Becker hinted at you was that the assert
macro might change behaviour underway: if you change the definition of
NDEBUG, a new inclusion of assert.h will redefine the assert-macro.
There are other uses that employes the fact that a new include of the
same file changes the meaning of the included source-code. A crude
implementation of templates spring to mind. You could define e.g.
std::vector via a macro and via some mechanism "instantiate" the
vector by including the macro.

I agree that it might have been a better idea to have some mechanism
to tell the compiler not to ignore a second include, but this should
have been changed loads of years ago, and such a solution is out of
the question today.

/Peter
 
L

LR

Juha said:
I did, and I still can't understand why including <assert.h> several
times would make a difference.

So you can change the behavior of assert each time you include it.
http://www-ccs.ucsd.edu/c/assert.html

And anyways, even if it did make a difference, wouldn't it be better
to simply have some kind of #pragma or whatever which tells the compiler
"it's ok to include this file more than once", the default behavior
being, when that #pragma does not appear, that multiple inclusions are
ignored?

The standard is explicit about this in 16.6, #pragma results in
implementation behavior so,

#pragma include_once

or whatever you might prefer, could result in your compiler starting up
an instance of Adventure.
http://en.wikipedia.org/wiki/Colossal_Cave_Adventure


LR
 
J

Juha Nieminen

peter said:
I agree that it might have been a better idea to have some mechanism
to tell the compiler not to ignore a second include, but this should
have been changed loads of years ago, and such a solution is out of
the question today.

Why? Would there be really any code out there which would break from
this kind of change? Especially since we are talking about C++ and
not C... (IMO if there *is* some C++ out there which would break from
this kind of change, it would really deserve a redesign.)
 
J

James Kanze

I did, and I still can't understand why including <assert.h> several
times would make a difference.

Never the less, it's very frequent. Anytime the profiler says
that your assertions are a performance problem. You don't want
to turn them off everywhere, nor even in every function in the
file where the performance problem occurs. Normally, you'd wrap
the offending function in something like:

#ifdef PRODUCTION
#define NDEBUG
#include <cassert>
#endif
// critical function...
#undef NDEBUG
#include <cassert>

The assert macro was carefully designed especially to support
this idiom. It's the way it was meant to be used; you're not
really supposed to defined NDEBUG globally, ever.

So while it is certainly "really ugly obfuscated preprocessor
trickery", anybody who's concerned with performance needs it.
And anyways, even if it did make a difference, wouldn't it be better
to simply have some kind of #pragma or whatever which tells the compiler
"it's ok to include this file more than once", the default behavior
being, when that #pragma does not appear, that multiple inclusions are
ignored?

Not really. Or at least, that's not enough. What is really
needed is two directives: #include and (say) #import. The first
would work exactly like it does today. The second would compile
the file in an isolated context, and then import whatever it
defined. So that things like "#define string char const*", for
example, would not cause problems if you did "#import <string>".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top