views:

148

answers:

4

How do you solve created by including a header file with the same name as another header file already indirectly included as a result of another include?

For instance:

// src/blah/a.hpp
#ifndef A_HPP
#define A_HPP

namspace blah
{

class A
{
}

}

#endif

// src/blah/b.hpp
#ifndef B_HPP
#define B_HPP

#includes "a.hpp"

namspace blah
{

class B
{
}

}

#endif

// src/foo/a.hpp
#ifndef A_HPP
#define A_HPP

namspace foo
{

class A
{
}

}

#endif

// src/foo/c.hpp
#ifndef C_HPP
#define C_HPP

#includes "../b.hpp"
#includes "a.hpp"       // won't be included due to multiple inclusion prevention

namspace foo
{

class C
{
}

}

#endif

In the last header file, a.hpp won't be included because of the multiple inclusion preprocessor guards. Really, this should be okay though since the classes are in different namespaces. I realize that the easy way is to just change the name of foo/a.hpp or to just give it a fake name in the multiple inclusion guard. Is there a better way?

EDIT I understand that you can solve this problem by using a more descriptive name in the #define and #ifndef directives (e.g. FOO_A_HPP and BLAH_A_HPP), but I want to know if that is the recommended or best way. Would some people recommend using a different file name as a better solution or does it not really matter? Would you recommend using the convention:

<NAMESPACE>_<CLASS>_HPP

instead of

<CLASS>_HPP

to give a better chance of avoiding these problems in general?

+4  A: 

You solve this, simply, by not using the same #define at the top ...

It would be better to use BLAH_A_HPP and FOO_A_HPP etc so that the #define also includes the namespace name.

Edit: Well personally I recommend doing the following:

1) Don't name headers the same (ie use different file name ... this doesn't always help) and use different #define names..
2) Don't name classes the same thing. Put 1 class per header and name the header after the class
3) If they are differentiated by a namespace use that namespace in the file name AND #define
4) Add an ID to you #define that is unique to you (I could use GOZ for example)
5) Make use of #pragma once. Its useful for the compilers that ise it.

Its all a matter of taste though. Choose a scheme that works for you and stick with it. There is no right or wrong. As long as it works and is consistent.

Goz
@Goz: understood, see my edit for more clarification on the question. Would you recommend the convention of NAMESPACE_CLASS_HPP in general? Is this better than just changing the filename or does it not matter?
deuberger
@deuberger: changing the filename will make no difference; the problem is due to the duplicated include guard name. And yes, I would recommend using something like NAMESPACE_CLASS_HPP for the include guard.
Mike Seymour
True its a "partial solution" ... I'll fix it :)
Goz
Good points. Thanks.
deuberger
A: 

Though there are no namespaces in C, I think this works for both C and C++.

#ifndef BLAH_B_HPP

and

#ifndef FOO_B_HPP
pmg
+1  A: 

When MSVC creates a class it will add a GUID to your guard name to avoid this sort of issue.

Greg Domjan
Nothing here says hes using MSVC, which isn't possible anyway since its C++.
mathepic
@mathepic: what do you mean it isn't possible since it's C++, what is this nonsense? Giving an example of standard way to make sure header guards is unique with background in where the idea came from, not saying that usage of MSVC is necessary.
Greg Domjan
@Greg Domjan MSVC is C.
mathepic
@mathepic: No it most definitely includes C++, and that is still besides the point.
Greg Domjan
A: 

As you have suggested yourself, the normal way to do this is to make your guard identifiers unique, by appending a GUID, or a complete path, or what have you.

In VC++ there's also a pragma to take care of multiple inclusion for you, so you don't need to write the #if defined(HUMPTYDUMPTY) bit yourself, it goes like

#pragma once

Has been around for a few iterations of VC++ now, but for other compilers you'd need to check. This also saves you the trouble of looking for unique names.

Edited: Just had a look and the Internet thinks that this is also in GCC. Seems like the #include style guards are very much 20th Century...

Alexander Rautenberg
Good point, though it seems like #pragma in general and #pragma once is not the preferred way. See: http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard.
deuberger
Just read the post about the pragma. I'm not really worried about performance here; just thinking that the more you have to type the more likely you are to make mistakes. If you do a lot of code porting between incompatible compilers then it may be a problem, though. Either way, nothing I'd lose any sleep over.
Alexander Rautenberg