J
Jason Heyes
I have read item 26 of "Exceptional C++" that explains a way of minimising
compile-time dependencies and, therefore, a way to improve compile speeds.
The procedure involves replacing #include directives with forward
declarations from within header files.
However, a potentially large number of source files may have previously
relied on the removed #include directives being present. Therefore it is
likely that a large number of source files will not compile as a result of
the modification and the "missing" #include directives must be inserted into
each of them. This is a pain.
Here is an example. The source file Z.cpp includes Y.h. The function defined
in Y.h is inlined.
// X.h
#include <iostream>
struct { void f() { std::cout << "X::f" << std::endl; } };
// Y.h
#include "X.h"
inline void y(X x) { x.f(); }
// Z.cpp
#include "Y.h"
int main()
{
y(X());
return 0;
}
When we use a forward declaration to remove the dependency of Y.h on X.h, we
see that Z.cpp must include X.h because main calls X::X(). So Z.cpp compiles
no faster than before. We might as well have left the dependency in
existence and saved ourselves all the extra work.
// X.h (as before)
// Y.h
class X;
void y(X x);
// Y.cpp
#include "X.h"
void y(X x) { x.f(); }
// Z.cpp
#include "Y.h"
#include "X.h"
// (rest as before)
The example shows that it doesn't always pay to minimise compile-time
dependencies. Here is the question. How do you make a judgement on what
dependencies should (or should not) be removed? Any thoughts are
appreciated.
compile-time dependencies and, therefore, a way to improve compile speeds.
The procedure involves replacing #include directives with forward
declarations from within header files.
However, a potentially large number of source files may have previously
relied on the removed #include directives being present. Therefore it is
likely that a large number of source files will not compile as a result of
the modification and the "missing" #include directives must be inserted into
each of them. This is a pain.
Here is an example. The source file Z.cpp includes Y.h. The function defined
in Y.h is inlined.
// X.h
#include <iostream>
struct { void f() { std::cout << "X::f" << std::endl; } };
// Y.h
#include "X.h"
inline void y(X x) { x.f(); }
// Z.cpp
#include "Y.h"
int main()
{
y(X());
return 0;
}
When we use a forward declaration to remove the dependency of Y.h on X.h, we
see that Z.cpp must include X.h because main calls X::X(). So Z.cpp compiles
no faster than before. We might as well have left the dependency in
existence and saved ourselves all the extra work.
// X.h (as before)
// Y.h
class X;
void y(X x);
// Y.cpp
#include "X.h"
void y(X x) { x.f(); }
// Z.cpp
#include "Y.h"
#include "X.h"
// (rest as before)
The example shows that it doesn't always pay to minimise compile-time
dependencies. Here is the question. How do you make a judgement on what
dependencies should (or should not) be removed? Any thoughts are
appreciated.