Re: [Development] C++20 structural types (was: C++20 @ Qt)
On Freitag, 4. November 2022 21:47:14 CET Thiago Macieira wrote: > On Friday, 4 November 2022 10:38:30 PDT Allan Sandfeld Jensen wrote: > > Can we even do that, and still preserve ABI and API? > > I don't see why not. QFlags is already standard-layout, trivially copyable > and trivially destructible. Changing the member from private to public > won't affect any of those properties. Right, but it is only forward compatible, as making members public gives new API options. So okay for a minor release, but not for a point release that also needs to be backwards compatible. Allan ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 structural types (was: C++20 @ Qt)
On Friday, 4 November 2022 10:38:30 PDT Allan Sandfeld Jensen wrote: > Can we even do that, and still preserve ABI and API? I don't see why not. QFlags is already standard-layout, trivially copyable and trivially destructible. Changing the member from private to public won't affect any of those properties. -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 structural types (was: C++20 @ Qt)
On Freitag, 4. November 2022 16:49:30 CET Thiago Macieira wrote: > I've just hit this: should we make some of our very simple types even > simpler so they're structural types[1] and thus can be passed as template > parameters? > > For example, QFlags. I've just tried it and I get: > > error: ‘QFlags’ is not a valid type for a template > non-type parameter because it is not structural > note: ‘QFlags::i’ is not public > > [1] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf Can we even do that, and still preserve ABI and API? Best regards, Allan ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] C++20 structural types (was: C++20 @ Qt)
I've just hit this: should we make some of our very simple types even simpler so they're structural types[1] and thus can be passed as template parameters? For example, QFlags. I've just tried it and I get: error: ‘QFlags’ is not a valid type for a template non-type parameter because it is not structural note: ‘QFlags::i’ is not public [1] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
Hi Ulf, On 04.11.22 12:13, Ulf Hermann via Development wrote: > One thing I haven't understood about the ordering problem is why we > cannot just define our "invalid" values to always be < any valid one and > equal to other invalid ones. This way we get at least weak ordering for > all our types and we're done. That's what we're currently doing, yes. At least for QDateTime. For QString, we have that isNull() compares equal to empty. Each class has it's own semantics. I'll have a look at QTypeRevision, but that prompted me to remember QOperatingSystemVersion, where we really, genuinely have several sets of values where elements from different sets are not ordered (Win10 There may be types where existing operator< work differently (*cough* > QTypeRevision), but that just means we need to emulate that same > behavior with the new operators. Without having looked at QTypeRevision, I agree in general. > Indeed the NaN behavior has always been a pain to deal with every time > I've encountered it. If we have a chance to avoid it, we should. > > What is the downside of such an approach? The (potential) downside is that it's arbitrary and classes might behave inconsistently (one sorts invalid before valid ones, the other vice versa). It may also be a bit more work to document (unless we choose not to mention that little detail). Or we can't reap any future tool support that might be developed for partial_ordering (sanitizers, etc). Overall, I don't feel strongly about it (no pun intended). From the ongoing discussion more and more examples pop up, though, where partial_ordering would be a really good idea (QVariant, QOSVersion, QTypeRevision?), and if those definite use-cases make people more familiar with partial_ordering, maybe invalid-as-unorderable would also come to be felt as more natural. Thanks, Marc ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] How qAsConst and qExchange lead to qNN
Hi, After getting my head washed by Volker, lemme provide background on these two functions. TL;DR: we created real maintenance and porting problems by not removing stop-gap functionality in a timely fashion, qNN presented as a way to ensure this won't happen again. Both qAsConst and qExchange are 1:1 reimplementations of std functionality we couldn't rely on back then (as_const is C++17 and exchange is C++14), so they're exactly equivalent to the std versions. Or were, when they were added. Neither std::as_const nor qAsConst have changed, so the replacement is easy: s/qAsConst/std::as_const/. It cannot not compile because qAsConst comes from qglobal.h and that transitively includes . This is what was intended from the get-go: https://codereview.qt-project.org/c/qt/qtbase/+/114548 > Intended as internal API, but not put into the QtPrivate > namespace to make it simpler to use. > > We could wait for std::as_const, but that is far, far > away (just entered the current C++17 draft as of this > writing), and the Qt containers with their tendency to > detach are a problem _now_. I don't remember why sometime later we (I) documented it as public API, but I failed to add the magic sentence > Use std::as_const if you can (C++17). qAsConst will be removed is a > future version of Qt We seem to be removing these kinds of sentences from API (currently on Gerrit for Q_FOREACH), but I don't think we should. Anyway, that's qAsConst. It does what std::as_const does, so moving to The Real McCoy is trivial. Unfortunately, as it always seems to happen, both std::exchange and qExchange changed. They're still 100% equivalent, but qExchange is now equivalent to std::exchange in C++20 (constexpr) and C++23 (conditionally noexcept, technically a DR), so we can _not_ blindly replace qExchange with std::exchange, because we only require C++17. It is important to dwell on the difference between the two: std::as_const never changed, so qAsConst never had to. std::exchange changed, so it was felt that qExchange had to, too. The outcome is that we don't need to maintain qAsConst, and can trivially port away from it, but we have (continued) to maintain qExchange, and can _not_ trivially port away from it. What was the mistake? The mistake was to not limit the qExchange implementation to the C++14 version, but directly going for C++20 semantics (constexpr; mea culpa) and therefore not being able to remove qExchange when we _could_ (in 6.0, when a C++14-only qExchange and std::exchange would have been semantically identical). Instead, we kept dragging it on with unclear semantics (C++14 or C++20?), until C++23 semantics were added to qExchange() extending the lifetime even further. Had we limited qExchange to C++14 and removed qExchange when we had the chance, this lock-in would not have happened. But why do the deprecation _now_? It turns out, when we decomposed qglobal.h to speed up compilation (a high-prio request from users), we ended up with a clean qglobal.h including only other includes, except qAsConst and qExchange for which we didn't find a good home. My idea, then, was to deprecate qAsConst and qExchange, introducing q20::exchange (see below), so that they could stay in qglobal.h, itself to be deprecated in favour of the more fine-grained headers and port the code base away from qAsConst and qExchange to pave the way for rolling out the finer-grained headers. It turns out I was too slow and qAsConst and qExchange are now in qttypetraits.h (go figure), and we have problems deprecating them _there_, because the Qt deprecation macros aren't defined, yet, when that file is included in some TUs. One problem after the other. This is just to illustrate that there's a very real cost associated with keeping stop-gap reimplementations of std functionality around for longer than absolutely necessary. So, late in Qt 5 I came to experiment with how we could break this vicious cycle: On one hand, we want to provide some std library reimplementations when we just don't want to or cannot wait for them to become available. But OTOH we want these to be stop-gaps, until we can depend on a version of C++ in which they ship, and remove them as soon as possible to avoid the above-mentioned trap where we need to maintain them indefinitely. And certainly, we don't want to follow the std implementation changes lest we never catch up with the std version. For some time, I thought just making these functions private would be enough (qmemory_p.h for q_make_unique), but private API means we can't use it in public headers. Also, there's no indication when we can remove the stop-gap again. Was make_unique C++14 or C++17? Hmm, hmm... Finally, there's the problem of whitespace: assume we've solved the problem with use in public headers, and I could write auto p = q_make_unique(foo, , bar, ); I can safely
Re: [Development] Using '#pragma once' instead of include guards?
Once we had QString and QByteArray (and the admittedly ill-conceived QStringRef). Now we have QStringView, QAnyStringView, QByteArrayView, ... and when asking what the prefered getter/setter-signature for "Qt-style" interfaces is the answer I get is "We'd guess $X, but the only guy that knows for sure is on holiday". And that's for "developers using Qt", not "developers _of_ Qt". Is that something you'd call "complicated"? While I can sympathize with the idea of #pragma once, this is not a fair comparison. The current set of classes, while complicated, also does a lot more than what we previously had. If you want the only the old functionality you can just restrict yourself to QString, QByteArray, and QStringView. That's not actually more complicated. But if you want classes that deal with UTF-8 and with views on different kinds of string data, you obviously need some more types. ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using '#pragma once' instead of include guards?
On Wed, Nov 02, 2022 at 02:25:25PM +, Marc Mutz via Development wrote: > Hi Volker, > > On 14.10.22 17:12, Volker Hilsheimer via Development wrote: > > Anyway, I’ve added the respective text to the coding convention wiki > > page. > > https://wiki.qt.io/Coding_Conventions > > Having read the thread in total, I'm surprised about this outcome. > AFAIK, we haven't had problems with traditional include guards, [Funnily enough, the same could be said for a significant part (read: pretty much all) the deprecations and API-removals since ~5.12] > yet, and no compelling use-case for #pragma once was presented, so I > don't see why we're now allowing it. The "user case" is that in Real Life(TM) (a) keeping the names of include guards sensible and consistent and "legal" is a pain. Talking about "identifiers reserved for use by C++ implementation" (double underscores, underscore plus uppercase - and don't think about what "uppercase" /actually/ means) is something that quite a few people don't want to do every second week. (b) it gives the concept a name. It is /one/ /short/ line that hardly can be misspelled, bears a meaning, and typically doesn't need discussion besides silencing the "Fire! Wolves! Non-Standard!" voices. Compare that to the three lines, that could be wrong, could mean something else, could use arbritrary names for the guards, which by itself are a perfect ground for bikeshedding and busy-work to "fix" them [1]. > Esp. since the rule as written is more > complicated than "always use header guards". [Oh "complicated"? Once we had QString and QByteArray (and the admittedly ill-conceived QStringRef). Now we have QStringView, QAnyStringView, QByteArrayView, ... and when asking what the prefered getter/setter-signature for "Qt-style" interfaces is the answer I get is "We'd guess $X, but the only guy that knows for sure is on holiday". And that's for "developers using Qt", not "developers _of_ Qt". Is that something you'd call "complicated"? Andre', wondering whether he actually should read this list during vacations. PS: [1] https://en.wikipedia.org/wiki/Busy_work - just to make sure: this bears a /negative/ connotated. ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
Hi, One thing I haven't understood about the ordering problem is why we cannot just define our "invalid" values to always be < any valid one and equal to other invalid ones. This way we get at least weak ordering for all our types and we're done. There may be types where existing operator< work differently (*cough* QTypeRevision), but that just means we need to emulate that same behavior with the new operators. Indeed the NaN behavior has always been a pain to deal with every time I've encountered it. If we have a chance to avoid it, we should. What is the downside of such an approach? best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
On Thursday, 3 November 2022 09:48:49 PDT Marc Mutz via Development wrote: >>> 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? On 03.11.22 18:38, Thiago Macieira wrote: >> We can use it until we can depend on C++20. Like QSpan, that's why it's >> there. Marc Mutz (4 November 2022 11:22) > 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. Since my comments on QDateTime are implicated here, I should note that - since it would be a behaviour change - an initial transition to a weak ordering that preserves invalid < valid could perfectly well suffice until we *do* transition to C++20 and *can* use std::partial_order, at which point I do think it would make sense to change our types with invalid (but supported) null-forms to make them incomparable, ideally all at the same time. > With the exception of qfloat32, I'm not aware of any Qt type that > would exhibit partial ordering semantics atm. I take it you mean qfloat16, whose NaN is incomparable, Eddy. ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
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. Thanks, Marc ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Sami Shalayel as approver
+1 Unsurprisingly, I'm part of the same team as Sami ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] Nominating Sami Shalayel as approver
Hi, I'd like to nominate Sami Shalayel as an approver for the Qt project. Sami is employed by the Qt Company and has been working since May on Qt, mostly on QtDeclarative, with a focus on qmltc. He made several good contributions there, and also participates in the review process of QML related patches. I trust him to be a good approver. Link to his gerrit dashboard: Patches: https://codereview.qt-project.org/q/owner:sami.shalayel%2540qt.io Reviews: https://codereview.qt-project.org/q/reviewer:sami.shalayel%2540qt.io Disclosure: I'm Sami's direct line manager at the Qt Company, and share an office with him. Fabian ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development