Holding things by pointer on the other hand actually does let you prevent the includes since you can just forward declare in the header, but it's an indirection :-/
Holding things by pointer on the other hand actually does let you prevent the includes since you can just forward declare in the header, but it's an indirection :-/
Then you get quickly into a situation where a header includes another header that's no longer needed by itself, but is used by another header in the same 'include tree', which in turn doesn't include the required header itself. Gets very messy very quickly.
It's much easier to notice and fix such situations in the top-level implementation file, and another advantage is that the "dependency complexity" of an implementation file is visible at a glance by looking at the include list at the top of the file.
TL;DR: It's not primarily for compilation speed, but for 'header hygiene' (but of course this will also eventually help with compilation speed as the project grows).
Another well known (at least among game devs) proponent of the the same idea is Our Machinery (granted, the whole idea makes a lot more sense in C than in C++, because in C declaration and implementation is usually much stricter separated into header and source files than in C++)
The idea is that each file (source or header) should include exactly those headers from which it uses things. In practice, it gets a bit more complicated has you don't want to include internal implementation headers and sometimes the same thing does not even have a canonical public header but IWUY does allow you to configure all that to your liking.
IME the best tools to solve the duplicated parsing (and compilation for templates) is to use IWYU [0] to cut down on unneeded includes and unity/jumbo builds to combine multiple translation units so common headers only need to be parsed once.
It would be a relatively simple thing to fix, if anyone is looking for a fun little project to learn a bit about GCC.
And it means you now need to deal with raw pointers, which often isn't optimal or preferred (over say references for example).
At least we'll get modules soon. That should reduce the need for some of these workarounds that are really mainly used to reduce compile times, and not to improve the code in any other meaningful way.
Reminds me of the good ol' days when Modula-2 had .def (definition) and *.mod2 (implementation) files, and you could compile the definition files alone to get binaries of the interface files that you could write and compile against in a typesafe way before the interfaces were even implemented
And as far as I recall the decoupling also made things compile fast (e.g. with Applications Systems Heidelberg's Modula-2 on the Atari ST 520+).
It may be possible to avoid that worst-case situation without such strict discipline, but with the no-recursive-include rule for sure it won't happen.
Of course this assumes that headers only include what they really need. If a header includes something it shouldn't (maybe an old dependency that was forgotten) the issue is old dependencies, and the fix is to remove it from the header once. With the article method you will need to remove it from every file that includes button (except maybe it is also used by another dependency and compile will fail).
Edit: I've realized the problem. If A includes B because it requires it, and C requires A and B, C will probably only include A and it will compile. Later if A is refactored and no longer requires B, removing it will break C. The solution is to always include what you use, even if it it's already included as dependency, as explained by another comment.