Consider a foo.cpp file with the following content
#include "foo.hpp"
int foo() {
return 7;
}
and its associated header
#pragma once
int foo();
The latter is obviously needed to make aware the following main function of the existence of foo:
#include <iostream>
#include "foo.hpp" // to make the name `foo` available
int main() {
std::cout << foo() << std::endl;
}
However, the #include "foo.hpp" seems to be redundant. Is there any reason I should keep it?
I've seen this practice in the codebase where I work on, but I guess there's many examples available in open source. For instance, as an example picked at random, look at src/builtin_builtin.h and src/builtin_bultin.cpp from the fish-shell code base: the former, beside the include guard, has
just
- one
#include, - two class declarations,
- and a function declaration.
One could put 2 in a fwd header, include it in the cpp file together with 1, and then the cpp file wouldn't need anymore to include its own header.
Some reasons to include the header (
fpp.hpp) from its implementation file (fpp.cpp):If you include
foo.hppfirst infoo.cpp, then compilation offoo.cppacts as a test thatfoo.hppis self-contained, meaning it can be successfully compiled without including anything else first. The Google C++ coding guidelines specifically recommend including the associated header first.It is good practice for
foo.hppto declare everything thatfoo.cppexports, and for everything else infoo.cppto have internal linkage in order to not pollute the global namespace. The GCC option-Wmissing-declarationswill report deviations from that practice, but it only works iffoo.cppincludesfoo.hpp.Sometimes (often, in fact), including
foo.hppis needed sofoo.cppwill compile. Most commonly,foo.hppdefines a type thatfoo.cppneeds, but it can also happen that function declarations are needed due to use before definition. I recommend to just do so consistently rather than trying to deduce whether it's necessary in each case.Occasionally, the compiler can diagnose mismatches between declarations and definitions. A nasty case I've seen is a header declaring a global
int xbut the implementation file defininglong x. Waste a day debugging that mistake, and I predict you'll resolve to include the associated header every time thereafter!Finally, there are no good reasons not to include the associated header. In particular, omitting that include will almost never make a measurable difference to compile time. There are ways of dramatically improving compile times by restructuring header dependencies (for example, use of forward headers), but this isn't one of them.
Acknowledgments: Point 1 was noted by BoP in a comment. MSalters' answer notes points 3 and 4.