[Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
Marc Mutz
marc.mutz at qt.io
Tue Nov 7 18:07:10 CET 2023
On 07.11.23 15:28, Ivan Solovev via Development wrote:
>
> So, my question is - shoud we support mixing C++17 and C++20 in one binary?
To be clear: This is not about Qt compiled with C++17 used in projects
compiled with C++20. This is about one .cpp file being compiled with
C++17 and another .cpp file from, broadly speaking, the same cmake
target, in C++20 (static builds are different; there, the whole
application incl. all "statically-linked libraries", is one executable).
What will happen is that the first TU is using a Q*Ordering return type
and the second TU is using the std::*_order return type. The linker will
them de-duplicate these per-TU inline function bodies and pick one of
them. Lets say, for the sake of argument, the C++17 one. Since the two
sets of ordering types are not binary compatible, and equivalent states
have different numerical values, the result of the call to the function
in the C++20 TU will be misinterpreted when it comes from the C++17
function. Of course, the whole thing is UB, so we may not even get so
far as a possible misinterpretation.
There are several ways to solve this:
1. Ban mixing different C++ versions in the same executable (= cmake
target).
This is probably the safest. If we allowed this instead, we'd need to
review all of our APIs to see whether we have a similar issue already.
2. always use only the Q*Ordering types.
Esp. since the numerical values of std::*_ordering and Q*Ordering don't
match, this will inject value-mapping code in future-proof idiomatic
C++20 code like
switch (lhs <=> rhs) {
case std::strong_order::less: ~~~;
~~~;
}
I would very much like to avoid that overhead.
3. make the Q*Ordering types binary compatible with the std ones.
If they're binary compatible, then while technically UB (ODR violation)
the situation would be very much like any other change to inline API.
There are two issues here: First, different std libs have different
values for the different states, so we'd need to #ifdef our own enum to
what the currently-used stdlib is using. Second, QPartialOrdering was
released independent of the C++20 comparison work, in Qt 6.0. So we
would need to dissociate the C++20 comparison stuff from it and rename
the existing 6.7 Q*Ordering types to, say, Qt:*_ordering, to start with
a clean slate.
My opinion:
- 1 is simplest, but we don't control how users compile our APIs, so
someone may still trigger this
- 3 is cleanest, therefore preferred: the complexity is on us, but the
resulting code is as efficient as can be, regardless of C++17 or C++20.
This is how it should be in C++.
- I don't like 2. It has it all backwards.
Thanks,
Marc
--
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
More information about the Development
mailing list