How do you maintain the #include statements in your C or C++ project? It seems almost inevitable that eventually the set of include statements in a file is either insufficie
I've been thinking about writing something that compiles each non-header file individually many times, each time removing an #include statement. Continue doing this until a minimal set of includes is achieved.
I think this is misguided, and will lead to "insufficient but just happens to work" include sets.
Suppose your source file uses numeric_limits, but also includes some header file, that for reasons of its own includes <limits>. That doesn't mean that your source file shouldn't include <limits>. That other header file probably isn't documented to define everything defined in <limits>, it just so happens to do so. Some day it might stop: maybe it only uses one value as a default parameter of some function, and maybe that default value changes from std::numeric_limits<T>::min() to 0. And now your source file doesn't compile any more, and the maintainer of that header file didn't even know that your file existed until it broke his build.
Unless you have crippling build problems right this minute, I think the best way to remove redundant includes is just to get into the habit of looking over the list whenever you touch a file for maintenance. If you find that you have dozens of includes, and having reviewed the file you still can't figure out what each one is for, consider breaking down into smaller files.
Detecting superfluous includes has already been discussed in this question.
I'm not aware of any tools to help detect insufficient-but-happens-to-work includes, but good coding conventions can help here. For example, the Google C++ Style Guide mandates the following, with the goal of reducing hidden dependencies:
In dir/foo.cc, whose main purpose is to implement or test the stuff in dir2/foo2.h, order your includes as follows:
dir2/foo2.h (preferred location — see details below).One big problem with the remove a header and recompile technique is that it can lead to still-compiling, but wrong or inefficient code.
Template specialization: If you have a template specialization for a specific type that is in one header and the more general template in another, removing the specialization may leave the code in a compilable state, but with undesired results.
Overload resolution: A similar issue - if you have two overloads of one function in different headers, but that take somewhat compatible types, you can end up removing the version that is the better fit in one case, but still have the code compile. This is probably less likely than the template specialization version, but it is possible.
As far as tools go, I've used Imagix (this was about 6 years ago) on windows to identify includes that are unneeded as well as includes which are needed but are indirectly included thru another include.
I usually create one source file (main.c, for example) and one header file for that source file (main.h). In the source file, I put all the main sort of "interface" functions that I use in that file (in main, it'd be main()), and then whatever functions I get after refactoring those functions (implementation details), go below. In the header file, I declare some extern functions which are defined in other source files, but used in the source file which uses that header. Then I declare whatever structs or other data types that I use in that source file.
Then I just compile and link them all together. It stays nice and clean. A typical include ... section, in my current project looks like this
#include<windows.h>
#include<windowsx.h>
#include<stdio.h>
#include"interface.h"
#include"thissourcefile.h"
//function prototypes
//source
there's an interface header which keeps track of the data structures I use in all of the forms in the project, and then thissourcefile.h which does exactly what I just explained (declares externs, etc).
Also, I never define anything in my headers, I only put declarations there. That way they can be included by different source files and still link successfully. Function prototypes (extern, static, or otherwise) and declarations go in the header, that way they can be used lots of times--definitions go in the source, because they only need to be in one place.
This would obviously be different if you were creating a library, or something like that. But just for internal project linking, I find this keeps everything nice and clean. Plus, if you write a makefile, (or you just use an IDE), then compiling is really simple and efficient.
I have the habit of ordering my includes from high abstraction level to low abstraction level. This requires that headers have to be self-sufficient and hidden dependencies are quickly revealed as compiler errors.
For example a class 'Tetris' has a Tetris.h and Tetris.cpp file. The include order for Tetris.cpp would be
#include "Tetris.h" // corresponding header first
#include "Block.h" // ..then application level includes
#include "Utils/Grid.h" // ..then library dependencies
#include <vector> // ..then stl
#include <windows.h> // ..then system includes
And now I realize this doesn't really answer your question since this system does not really help to clean up unneeded includes. Ah well..