Hi, DL;DR: Use #pragma once in all non-installed headers
The question recently came up "what is a private header". And the answer isn't just "_p.h, of course". We have tons of headers that are "private" without being marked as such with _p.h and "We mean it." comment. The first realization is that there are degrees of privateness: We have the installed private headers, and then we have non-installed/able headers, e.g. in plugins, or tools. So we have - public installed headers (subject to SC and BC, syncqt and headerscheck runs on them) - semi-public installed headers (like above, but not subject to SC (but BC) (_impl.h, stuff in QtPrivate namespaces, qNN, ...) - private installed headers (not subject to SC/BC/headersclean, but syncqt runs on them, must have "We mean it." comment) - private non-installed headers (not subject to any constraint, not even syncqt runs on them) We can now look at what signs we currently have available that guide a reader to learn which kind of header he's looking at. For the first, we have only location in $SRCDIR. For the second, we have _impl.h and/or "We mean it." comment. For the third, which is easiest to distinguish, we have _p.h and "We mean it." comment. This is enforced by syncqt, which is why we can rely on it 100%. For the last one, we again have just the location in $SRCDIR. The problem is, obviously, that the first and last cases are nearly indistinguishable and require non-local reasoning to answer. I think we have improve on this. With Volker's email we gave ourselves permission to use #pragma once for "non-SDK" (= non-installed) headers, and banned it for installed headers. So if we could make syncqt complain if a processed (= installable) header contains #praga once, we could then flip the coin and use an actual #pragma once as a static assertion that the header is not installed/able. If we do this going forward, we can then easily distinguish the four header kinds: - public installed headers have a traditional header guard - semi-public installed headers ditto, except that have _impl.h suffix or "We mean it" comment - private installed headers ditto, _p.h suffix and "We mean it" comment - non-installed/able headers have #pragma once I've implemented the check in syncqt.cpp and ported xcb over, see https://codereview.qt-project.org/q/topic:pragma-once I'm not suggesting to do such a port for all plugins. XCB is just a test balloon, but we might want to apply the #pragma once trick for new code going forward. Thanks, Marc On 12.10.22 12:35, Volker Hilsheimer via Development wrote: > >> On 11 Oct 2022, at 22:11, Thiago Macieira <thiago.macie...@intel.com> wrote: >> >> On Tuesday, 11 October 2022 12:25:13 PDT Kyle Edwards via Development wrote: >>> Speaking as co-maintainer of CMake, we have effectively required #pragma >>> once to build CMake itself since August 2017, we officially codified >>> this as policy in September 2020, and we will soon be writing a >>> clang-tidy plugin to enforce this in our CI. We have not received any >>> complaints about it. Just my $0.02. >> >> Thanks for the information. This confirms what we already knew that all >> systems >> and compilers where Qt would be compiled do support it. >> >> However, neither Qt Creator nor CMake are libraries. They are not comparable. > > > Thanks all for sharing your insights and digging up the previous discussions > as well. > > The summary of all this then seems to be: > > - ok to use '#pragma once’ in headers that are not designed to be included by > Qt users, i.e. in tools, applications, examples and demos, tests > - for everything else, in particular for public and, for consistency’s sake - > private headers in Qt, we continue to use conventional include guards > > Rationale: #pragma once is not well enough defined and not part of the > standard, and we cannot make any assumptions about how Qt is installed, used > as part of a larger SDK etc. So best to stay conservative. > > If that’s not entirely off, then I’d like to put this into > https://wiki.qt.io/Coding_Conventions [1], preempting perhaps a new thread on > this topic in a few years. > > Volker > > [1]: And since that page seems rather outdated - e.g. we do use dynamic_cast > in Qt today, and the suggestion to normalize signals and slots should rather > suggest to make connections via PMF syntax - perhaps it’s time to move this > to a QUIP where we can discuss and review such changes in gerrit. I won’t > have time to do that for a while (perhaps ditto for > https://wiki.qt.io/Qt_Coding_Style), but perhaps someone else wants to give > this a shot. > > _______________________________________________ > Development mailing list > Development@qt-project.org > https://lists.qt-project.org/listinfo/development -- Marc Mutz <marc.m...@qt.io> Principal Software Engineer The Qt Company Erich-Thilo-Str. 10 12489 Berlin, Germany www.qt.io Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen Sitz der Gesellschaft: Berlin, Registergericht: Amtsgericht Charlottenburg, HRB 144331 B -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development