[Development] Using '#pragma once' instead of include guards?
Kai Köhne
Kai.Koehne at qt.io
Mon Mar 4 15:56:53 CET 2024
Hi Marc,
I've nothing against using '#pragma once' for private/internal headers.
But you said you mainly want to have this to differentiate between different types of headers. If this is the motivation, I think we can make this differentiation even more explicit. For instance, public headers could get a
// This header is part of the public Qt API.
comment. Much like the 'We mean it', or 'pragma once', syncqt could enforce this for public headers, and error out if it's used for non-public ones.
Kai
________________________________
From: Development <development-bounces at qt-project.org> on behalf of Marc Mutz via Development <development at qt-project.org>
Sent: Thursday, February 29, 2024 11:02
To: development at qt-project.org <development at qt-project.org>
Subject: Re: [Development] Using '#pragma once' instead of include guards?
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.macieira at 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 at qt-project.org
> https://lists.qt-project.org/listinfo/development
--
Marc Mutz <marc.mutz at 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 at qt-project.org
https://lists.qt-project.org/listinfo/development
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20240304/b23d02b0/attachment-0001.htm>
More information about the Development
mailing list