9

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?

Mike Seymour
  • 235,407
  • 25
  • 414
  • 617
deuberger
  • 3,450
  • 6
  • 29
  • 32
  • Why is this tagged as C? – Oliver Charlesworth Sep 10 '10 at 20:11
  • I always put the namespace in my guards. Automated tools will put a GUID as the header guard. The whole point is that they **MUST** be unique (not just in your project but preferably unique across all files in all the world in all dimensions if possable). – Martin York Sep 10 '10 at 20:55

5 Answers5

11

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
  • 58,120
  • 22
  • 114
  • 192
  • 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 Sep 10 '10 at 20:25
  • @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 Sep 10 '10 at 21:32
  • True its a "partial solution" ... I'll fix it :) – Goz Sep 10 '10 at 21:46
4

I am surprised that no-one mentioned the simple solution of using #undef A_HPP as below

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

#includes "../b.hpp"
#undef A_HPP
#includes "a.hpp" 
...

This is particularly good if foo/c.hpp is the only file one can or is allowed to change.

onlooker
  • 517
  • 4
  • 3
1

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

Greg Domjan
  • 13,307
  • 6
  • 39
  • 59
  • Nothing here says hes using MSVC, which isn't possible anyway since its C++. – alternative Sep 10 '10 at 21:28
  • @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 Sep 13 '10 at 14:48
  • @mathepic: No it most definitely includes C++, and that is still besides the point. – Greg Domjan Sep 13 '10 at 23:05
0

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
  • 98,431
  • 10
  • 118
  • 189
0

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
  • 2,125
  • 1
  • 20
  • 19
  • 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 Sep 13 '10 at 16:43
  • 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 Sep 13 '10 at 19:33