3 ms·
Extreme #include discipline for C++ code
- theamk 3y ago> We try to mitigate it with #ifdef guards, #pragma once etc. but in my experience those band-aids don’t solve the problem. Huh, I wonder why he thinks so? "#pragma once" works pretty well and completely eliminates "double-parsing includes" problem within single file. (And if you want to eliminate multiple parsing of includes _across_ the files, you need something like modules, no amount if include discipline will help) Pretty sure that whatever beneficial effect author gets (if any), it's not from double include elimination. A much more likely explanation is that by making includes painful, author self-encourages to include less stuff and to keep simpler hierarchy.
- rewmie 3y ago> In real C++ codebases the same headers are unnecessarily re-included and re-parsed hundreds of times. This scenario is only conceivable if you do not use include guards, and not protecting includes with include guards is a very fundamental mistake. This whole blog post is baffling. Include header management is a basic thing in C++ development for decades, and there are countless techniques to minimize the need for includes and interfaces in include headers. Include guards were never a problem and they are taught as programming 101. And also taken from the blog post: > Over time the sloppiness accumulate and we might end up with inter-dependent, circular mess. You just want to #include "Button.h" and somehow it ends up bringing in NuclearPowerPlant.h I think this hints at the root cause of the blogger's problem: failure to architect projects and properly modularize them. You only risk including stuff you don't need if you design your interface to include stuff you don't need. Your modules need to provide a set of interface headers, and those interface headers are designed to be included everywhere and anywhere. You only include things in those headers that you need to access to interface with your module. This means stuff like vocabulary types and your own components. If you provide a set of interface headers that include NuclearPowerPlant.h, that is on you. There is a very easy way to keep this sort of thing in check in a C++ project. For each and every single module in your software project, you explicitly separate a module's interface/public headers from source files and private headers. Interface/public headers are kept in a separate ./include/<namespace> folder, and you make absolutely sure that header files stored in this path don't drag in anything that should not be a part of the interface. Afterwards, any component that drags in a module as a dependency only gets access to the include/public headers. That's it.