>On another note: C++ compiler should by default keep statistics about the chain of #include's / parsing during compilation and dump it to a file at the end and also summarize how badly you're re-parsing the same .h files during build.
Clang does offer something very close to this, and if you use it you'll find parsing the same/duplicate header files contributes on the order of microseconds to the overall compile time. Your article is from 1989, which is likely before compilers implemented duplicate header file elimination [1], but nowadays all C++ compilers optimize the common #ifndef/#define header guard as well as #pragma once so that they entirely ignore parsing the same file over and over again.
Correct me if I'm wrong, but I believe the parent comment's strategy of only #including header files within .c files only helps reduce duplicate header file parsing within each compilation unit. So it wouldn't do anything to improve the case you mention (duplicate header compilation across compilation units) anyway, while adding much additional overhead in manually tracking header file dependencies.
Also, given your experience in compilers - keen to see if you agree that because modern compilers optimize away re-scanning of the same header file within a compilation unit anyway (in the presence of include guards), the strategy of only #including header files within .c files is close to useless.
The not rescanning if the #include guards are there goes back to the mid 1980s. It's not a modern feature :-)
> the strategy of only #including header files within .c files is close to useless
It probably is. It also means the user of the .h file has to manage the .h file's dependencies, which is not the best practice. .h files should be self-contained.
GCC optimized the handling of headers with include guards 30 years ago already.
If you think most of your compile time is spent in preprocessing, benchmark a clean build with the optimization set to -O0 versus your full optimization like -O2 or whatever you are using.
Both builds perform preprocessing; thus the preprocessing time is bounded by the total time spent in the -O0 build: if the actual semantic analysis of tokens and code generation at -O0 were to take next to no time at all, then we would have to attribute the time to tokenizing and preprocessing. But even then, all the additional time observed under -O2 is not tokenizing and preprocessing.
Clang does offer something very close to this, and if you use it you'll find parsing the same/duplicate header files contributes on the order of microseconds to the overall compile time. Your article is from 1989, which is likely before compilers implemented duplicate header file elimination [1], but nowadays all C++ compilers optimize the common #ifndef/#define header guard as well as #pragma once so that they entirely ignore parsing the same file over and over again.
[1] https://gcc.gnu.org/onlinedocs/cpp/Once-Only-Headers.html