views:

965

answers:

13

I've used some very large scale systems and never seen a required order, but came across it recently. Does the STL or STD library or even Boost have any cases where certain includes must come in a certain order?

+8  A: 

This definitely sounds like a bad design. If somehow a specific order was required, the library should provide one header that includes the other ones in the correct order.

As far as boost, and the STL, I'm pretty sure I haven't encountered this situation yet.

Flame
+3  A: 

Does the STL or STD library or even Boost have any cases where certain includes must come in a certain order?

I have never come across this and if it is so then the authors must be notified ASAP. And oh yes its a very bad design.

SDX2000
+1: bad smell. And there's a standard #ifdef sandwich to assure that all .h's include all their proper dependencies.
S.Lott
+1  A: 

If the functions and/or classes contained in header (say, A.h) depend on functions and/or classes defined in another header (say, B.h), I prefer to include the latter in the first, rather to force the users of the first one to include both in a particular order.

Yes:

// A.h
#pragma once
// or the #ifndef trick
#include "B.h"

// A.cpp
#include "A.h"

No:

// A.h
#pragma once
// or the #ifndef trick
//#include "B.h"

// A.cpp
#include "B.h"
#include "A.h"
Eduardo León
+3  A: 

That is a 'bad thing'. A better way has been mentioned; but I'll elaborate.

//a.h
#ifndef _A_H_
#define _A_H_

//... code ...

#endif
// -----------------
//b.h
#ifndef _B_H_
#define _B_H_
#include a.h

//... code ...

#endif
// -----------------
//main.cpp Try 1
#include "b.h" //<- okay!  b includes a, then does b
// -----------------
//main.cpp Try 2
#include "a.h" //<- includes a
#include "b.h" //<- okay!  b includes a, but skips redefining it, then does b
// -----------------
//main.cpp Try 3
#include "b.h" //<- b includes a, then does b
#include "a.h" //<- okay!  a skips redefining itself!
// -----------------
//main.cpp Try 4
#include "a.h" //<- fail!  b is not included anywhere =(
Tom Ritter
Hmmm, I think you messed up your 'a's and 'b's. In line 5, in file a.h, you are including b.h. But in latter comments you say: b includes a.
Marcelo MD
Correct, I fixed.
Tom Ritter
+26  A: 

Does the STL or STD library or even Boost have any cases where certain includes must come in a certain order?

For the standard, the answer is emphatically, no. I imagine the same is true for Boost, though I haven't looked it up.

From the C standard:

Standard headers may be included in any order; each may be included more than once in a given scope, with no effect different from being included only once, except that the effect of including <assert.h> depends on the definition of NDEBUG (see 7.2).

the C++ standard has similar wording.

My preference is that headers should include their own dependencies, but I've worked with people who believe this to be 'wasteful'. In my opinion, not having headers include their dependencies is a worthless early optimization.

Michael Burr
Especially since it's easy enough to put guard conditions on a header so that they are only ever included once, making the "optimization" completely useless.
Eclipse
Agree. Compilers can optimize away the extra includes and if you skip them you will get into a mayhem if one of your included headers changes into not including something you need. Forward declarations aside, when they apply, that is.
David Rodríguez - dribeas
+6  A: 

Needing to specify includes in a specific order almost always indicated a design problem. One way to reduce the possibility of inadvertantly doing this, is to get into the practice of including a class's header file as the first #include in the implementation file.

// A.cpp
#include "A.h"
#include "boost/shared_ptr.hpp"
#include <vector>

class A {
// ...
};

This way if, for example, A.h uses a vector without the right #include, A.cpp won't compile.

I can't remember where I picked this up; it might have been from "Large Scale C++ Design" by Lakos (a great book that could really use an update).

KeithB
+1  A: 

I like including headers in alphabetical order - makes it easy to see what I've already done.

If a lib won't work because it's in the wrong order, then it's broken and should be fixed so as to be order-independent.

warren
A: 

Not to my knowledge. It's pretty bad practice. I've run into it recently with a Windows header and some weird interface in my code, though.

Paul Nathan
+1  A: 

To me it is a bad design that, unluckily, happens to be in win32 API with socket/socket2 includes, if I recall correctly. The result is that an error in inclusion order will trigger a set of errors that just happen to come from nowhere and may be hard to debug in the cases where the dependency changes the definitions but the code still compiles.

In any other case, you will still run into trouble. If you don't include header x.h because y.h already includes it, then your code is dependent on y.h dependency on x.h. If at a later time y.h is refactored and it no longer requires y.h, the removal of the include will break your code base. This is a sign of coupling (even if not at the class level): changes in one part of the code base need to propagate and extend to other parts of code.

David Rodríguez - dribeas
windows.h and gl.h have the same problem, sadly
Jasper Bekkers
A: 

You should be using include guards and forward declarations, in that way you shouldn't have much problems with the order of including headers.

Sometimes it's still required that a header is included first or last, no idea why.
(For example: In the Source SDK)

TomWij
+1  A: 

It's perhaps a sign that you're using MFC, which might in turn indicate bad design (joke... or is it?)

(At least, the last time I looked at MFC, it was really picky about where you included <windows.h>)

Daniel Earwicker
+3  A: 

It's a common technique to include a project level compatibility header (say compat.h) as the first header of any .c/.cpp source files, which defines a bunch of required macros like __STDC_LIMIT_MACROS, __REENTRANT and other project wide macros to affect the subsequent behavior of standard headers.

I first saw this usage long time ago by a competent programmer for an internal library. Later I saw 'git' (the infamous dvcs) project use this technique as well.

obecalp
I agree that this type of configuration-setting might be one area where a requirement for needing a header to be included in a particular order makes some sense. Another time is when you're using precompiled headers (but I'm no big fan of precompiled headers).
Michael Burr
I've done that before, but at this point I really prefer those macros to be defined by my build args (g++ -D__STDC_LIMIT_MACROS ...) than to be part of the source themselves. To each his own, though.
Tom
Well there is no clean way to express some of the conditions (platform, compiler) in build args (which makes the build system much uglier)
obecalp
A: 

Yes, requiring a certain order for includes in c++ is a sign of bad library/header design.

Though forward declarations may require more than one file to be included in order to fully use a class. See example below:

// A.h

class B; // forward declaration

class A
{
    void doStuff(const B& b);
};

// main.cpp

#include <A.h>
#include <B.h>

int main()
{
    A a;
    B b;
    a.doStuff(b);
}
dalle
This is fine, because the order of the includes in main.cpp can be reversed without a problem. It would be a problem if A.h didn't use a forward decl and didn't include B.h That would require main.cpp to include B.h before including A.h
KeithB