[Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)

Marc Mutz marc.mutz at qt.io
Fri Nov 4 11:22:02 CET 2022

Hi Thiago,

On 03.11.22 18:38, Thiago Macieira wrote:
> On Thursday, 3 November 2022 09:48:49 PDT Marc Mutz via Development wrote:
>> On 03.11.22 16:17, Thiago Macieira wrote:
>>> For some classes, we could postpone changing anything until C++20 is
>>> required.
>> You lost me there. Why do you think so? Because of the sentence above?
>> Requiring C++20 won't be a BC break, so we'd still have all the old
>> exported relational operators to QT_REMOVED_SINCE.
> A simple question of code readability. If it's not that important and it makes
> the code significantly uglier, we can simply postpone until it's not ugly.

Yes, we could postpone, but I feel that would be a disservice to both us and 
our users.

To us, because we simply don't have the bandwidth to do all C++20 
changes at once, so we need to select which ones we can do before we 
require C++20, and this is one of them.

To our users, because we currently don't have a clue whether our 
relational operators are free of C++20 ambiguities. We _think_ we caught 
them all, but we don't have a C++20 build on the CI, yet to know for 
sure, and,even if we did, we typically don't have the test coverage to 
test all combinations (incl. const/mutable and l/rvalue). Ambiguities 
are detected at call time, not declaration time, so we need exhaustive 
checking, anyway. I believe it's better to fix this issue before we 
require users to use C++20, forcing them into exposing our remaining 
bugs. And to fix them consistently. A user doesn't care whether his 
C++20 build breaks because of QJsonValue or QWaylandBufferRef.

>>> Meanwhile, we have qcompare.h.
>> Here, too, I feel lost. I'm struggling to see what a NIH
>> std::partial_ordering w/o the weak and strong counterparts and w/o op<=>
>> language support could achieve, except another vocabulary type mismatch.
>> Can you elaborate?
> We can use it until we can depend on C++20. Like QSpan, that's why it's there.

The difference is that QSpan vs. std::span doesn't create an impedance 
mismatch. QPartialOrdering vs. std::partial_ordering does, esp. since 
QPartialOrdering lacks an implicit conversion to/from 
std::partial_ordering, and the member names are different.

> Or the methods can simply return int, like I intended in QCborValue.

That's what I was thinking, yes.

>> Meanwhile, in a Jira comment, Eddy discovered a potential problem with
>> partial_ordering::unordered: we have a lot of types that have
>> std::optional folded into them (isNull/isValid) and, if they're ordered,
>> they need to have decided on a total order, ie. incl. for invalid/null
>> ones (QDateTime sorts invalid before valid e.g.). These types' op<=>
>> could now return unordered for invalid values, but that would change the
>> semantics of the op< derived from it vis a vis the existing op<.
> What's the recommendation? Create a total order where null < empty < any non-
> empty, or use partial ordering?

For new classes, knowing what I know now, I'd use partial ordering 
(though I'd also ask to consider avoiding baking in optional<> semantics 
to elegantly side-step the issue). For existing classes, we need to keep 
the total order they most likely are currently using. With the exception 
of qfloat32, I'm not aware of any Qt type that would exhibit partial 
ordering semantics atm. Whether we then switch to a partial order come 
Qt 7 is a different question. I would make that contingent on how 
support for partial_ordering in the wider C++ ecosystem in coming along.


More information about the Development mailing list