Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include File Ordering Strategy

I've seen fairly consistent advice that an implementation file (.cc / .cpp) should include its corresponding class definition file first, before including other header files. But when the topic shifts to header files themselves, and the order of includes they contain, the advice seems to vary.

Google coding standards suggest:

  1. dir2/foo2.h (preferred location — see details below).
  2. C system files.
  3. C++ system files.
  4. Other libraries' .h files.
  5. Your project's .h files.

It is unclear what the difference is between entry 1 and 5 above, and why one or the other location would be chosen. That said, another online guide suggests this order (found in the "Class Layout" section of that doc):

  1. system includes
  2. project includes
  3. local includes

Once again there is an ambiguity, this time between items 2 and 3. What is the distinction? Do those represent inter-project and intra-project includes?

But more to the point, it looks as if both proposed coding standards are suggesting "your" header files are included last. Such advice, being backwards from what is recommended for include-ordering in implementation files, is not intuitive. Would it not make sense to have "your" header files consistently listed first - ahead of system and 3rd party headers?

like image 470
Brent Arias Avatar asked Feb 01 '11 21:02

Brent Arias


3 Answers

The order you list your includes shouldn't matter from a technical point of view. If you designed it right, you should be able to put them in any order you want and it will still work. For example, if your foo.h needs <string>, it should be included inside your foo.h so you don't have to remember that dependency everywhere you use foo.

That being said, if you do have order dependencies, most of the time putting your definition file last will fix it. That's because foo.h depends on <string>, but not the other way around.

You might think that makes a good case for putting your definition file last, but it's actually quite the opposite. If your coding standards require the definition first, your compiler is more likely to catch incorrect order dependencies when they are first written.

like image 168
Karl Bielefeldt Avatar answered Oct 13 '22 19:10

Karl Bielefeldt


I'm not aware of any verbatim standard but as a general rule of thumb include as little headers as possible especially within other header files to reduce compile times, conflicts, and dependencies. I'm a fan of using forward declaration of classes in header files and only including the header and definition on the .cpp side whenever I can afford to do so.

That said my personal preference is below:

For Headers:

  1. C++ headers
  2. 3rd party headers
  3. other project headers
  4. this project's headers

For Source:

  1. precompiled header file
  2. this source file's header
  3. C++ headers
  4. 3rd party headers
  5. other project headers
  6. this project's headers

Pointers or suggestions are usually to avoid conflicts and circular references, otherwise it's all personal preference or whatever policy you prefer adhere to for collaborative projects.

like image 43
AJG85 Avatar answered Oct 13 '22 20:10

AJG85


Regarding Google's style:

There is no ambiguity, at all.

The first header included should be the header related to this source file, thus in position 1. This way you make sure that it includes anything it needs and that there is no "hidden" dependency: if there is, it'll be exposed right away and prevent compilation.

The other headers are ordered from those you are the least likely to be able to change if an issue occurs to those you are the more likely to. An issue could be either an identifier clash, a macro leaking, etc...

By definition the C and C++ systems headers are very rarely altered, simply because there's so many people using them, thus they come second.

3rd party code can be changed, but it's generally cumbersome and takes time, thus they come third.

The "project includes" refer to project-wide includes, generally home-brawn libraries (middle-ware) that are used by several projects. They can be changed, but this would impact the other projects as well, they come fourth.

And finally the "local includes", that is those files who are specific to this project and can be changed without affecting anyone else. In case of issue, those are prime candidates, they come last.

Note that you can in fact have many more layers (especially in a software shop), the key idea is to order the dependencies starting from the bottom layer (system libs) to the top layer.

Within a given layer, I tend to organize them by alphabetical order, because it's easier to check them.

like image 43
Matthieu M. Avatar answered Oct 13 '22 21:10

Matthieu M.