While, in principle,1 C++20 marks the beginning of the end of our long, collective, inclusion nightmare the painful truth is that many C++ developers are going to be dealing with header files for years to come. And I've heard of no plans to bring a modules system to plain C at all.
But at least we have decades of experience from which to derive best practices and better tools to automate or enforce those practices. Right?
Some of the best practices:
- Every header should have include guards.2
- Don't
#include
files unless you need declarations or definitions found therein. Where possible prefer forward declarations or forward declaring headers (likeiosfwd
). - Explicitly include headers to cover everything you need. Do not rely on transitive includes.
None of this is particularly controversial (leaving out the holy war over how to protect files from multiple inclusion), but I find that I have a minor interpretational difference with include-what-you-use (AKA IWYU: one of the leading tools for automating these rules). You see IWYU asks me to include in my implementation file things I already included in my the associated header file. Now, that is a strict interpretation of rule (3), so why does it bother me? Apparently I think of the header and implementation as two parts of a single logical unit rather than two independent things. I mean, those things should be maintained together so the danger of relying on the transitive inclusion is mitigated.
Of course, if I was implementing the tool I'd at the very least start with the current behavior. Simply because it's going to be very hard for the tool to know that this header really and truly does go with that implementation. I mean usual if they have the same stem that's a good clue, and in project where headers and implementations can sit in the same directories that is also helpful. But some layouts separate the interface files, so then what?
1 By now a non-trivial fraction of C++ coders are able to use the 2020 standard, but that doesn't mean that they are able to use modules. Support has been pretty slow even in compilers and build tools maintainers are stuggling with some real problems inherent in the pure flexibility of the module standard in C++.
2 Yes, I know, in the Windows world many people strongly advocate
for #pragma once
instead, and avoiding the possibility of name
collisions is a big advantage in my book. But it remains non-standard which is
why some
major style guides and
the core
guideline still insist on classic approach.
No comments:
Post a Comment