I think it's generally good practice to #include
the header for any types used in a CPP file, regardless of what is already included via the HPP file. So I might #include <string>
in both my HPP and CPP, for example, even though I could still compile if I skipped it in the CPP. This way I don't have to worry about whether my HPP used a forward declaration or not.
Are there any tools that can enforce this #include
coding style? Should I enforce this coding style?
Since the preprocessor/compiler doesn't care whether the #include
is coming from the HPP or CPP, I get no feedback if I forget to follow this style.
Best Answer
This is one of those "should" rather than "shall" kinds of coding standards. The reason is that you would pretty much have to write a C++ parser to enforce it.
A very common rule for header files is that they must stand by themselves. A header file must not require that some other header files be #included before including the header in question. This is a testable requirement. Given some random header
foo.hh
, the following should compile and run:This rule has consequences with regard to use of other classes in some header. Sometimes those consequences can be avoided by forward declaring those other classes. This isn't possible with a lot of the standard library classes. There's no way to forward declare a template instantiation such as
std::string
orstd::vector<SomeType>
. You have to#include
those STL headers in the header even if the only use of the type is as an argument to a function.Another problem is with stuff that you incidentally drag in. Example: consider the following:
file foo.cc:
Here
bar
is a classFoo
data member that is of typeBar
. You've done the right thing here and have #included bar.hh even though that would have to have been included in the header that defines classFoo
. However, you haven't included the stuff used byBar::Bar()
andBar::add_item(int)
. There are many cases where these calls can result in additional external references.If you analyze
foo.o
with a tool such asnm
, it will appear that the functions infoo.cc
are calling all kinds of stuff for which you haven't done the appropriate#include
. So should you add#include
directives for those incidental external referencesfoo.cc
? The answer is absolutely not. The problem is that it is very hard to distinguish those functions that are called incidentally from the ones that are called directly.