Re: [Development] API style guide: scoped enum or not?
On Wednesday, 14 June 2023 14:26:52 PDT Giuseppe D'Angelo via Development wrote: > I think this should be a completely different question than the usage of > scoped enums in new code. For instance, I'm all for scoped enums and > against such refactoring. The refactoring *could* be done now, but it's a massive code update and can't be helped with macros. It would increase the size of most headers and substantially so for qnamespace.h, which might impact compilation time. Therefore, I oppose such a change now. But I do support a statement of intent that in Qt 7 we want to revisit this and change where possible. It might be a macro-enabled backwards compatible API, or maybe we'll be able to use "using enum" by then. -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
Il 14/06/23 22:15, Volker Hilsheimer via Development ha scritto: -1 to B from me as well. We can allow unscoped enum as an acceptable (if explained) exception from the rule of using scoped enums. Otherwise we remove a tool from our toolbox, even if it has it’s uses in certain (increasingly rare, perhaps) situations. More importantly, I don’t agree with the footnoted proposal of making all currently unscoped enums scoped in Qt 7. Such a change would cause a massive porting effort (tool or not), with zero value for users. There might be exceptions where we have genuine issues from certain enums being unscoped, we can fix those with appropriate porting aids and compatibility wrappers/aliases. I think this should be a completely different question than the usage of scoped enums in new code. For instance, I'm all for scoped enums and against such refactoring. My 2 c, -- Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer KDAB (France) S.A.S., a KDAB Group company Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com KDAB - The Qt, C++ and OpenGL Experts smime.p7s Description: Firma crittografica S/MIME -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On Wednesday, 14 June 2023 12:49:22 PDT Allan Sandfeld Jensen wrote: > As discussed earlier. Better naming in many cases until we can depend on > C++20 in API. There's nothing in C++20 that would allow us to design APIs differently. You may be thinking of C++23 "using enum" feature, which is barely supported anywhere and doesn't help us in any way I can see. It might allow us in the future to change our existing unscoped enums to scoped, but until then there's little we ca do. So this question is strictly a C++11 scoped enum one. -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
+1 to A and C. > On 14 Jun 2023, at 21:49, Allan Sandfeld Jensen wrote: > > On Mittwoch, 14. Juni 2023 17:48:27 CEST Thiago Macieira wrote: >> On Wednesday, 14 June 2023 08:35:16 PDT Marc Mutz via Development wrote: >> B) new enums MUST be scoped, also when nested in classes¹² > > -1 Disagree -1 Disagree >>> >>> Ok. But _why_? (Q to both) >> >> I'm inclined to agree with (B), so I'd like to understand the objections. > > As discussed earlier. Better naming in many cases until we can depend on > C++20 in API. I disagree with designing API for standards we are not yet > allowed to use. And there are a few rare cases with flags or other composite > value types, where the implicit casting is desirable. I wouldn't mind saying > scoped enums are the preferred default, and any unscoped enum needs to be > justified in the commit message, but I would hate to ban them out right. > > Best regards > Allan -1 to B from me as well. We can allow unscoped enum as an acceptable (if explained) exception from the rule of using scoped enums. Otherwise we remove a tool from our toolbox, even if it has it’s uses in certain (increasingly rare, perhaps) situations. More importantly, I don’t agree with the footnoted proposal of making all currently unscoped enums scoped in Qt 7. Such a change would cause a massive porting effort (tool or not), with zero value for users. There might be exceptions where we have genuine issues from certain enums being unscoped, we can fix those with appropriate porting aids and compatibility wrappers/aliases. Volker -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On Mittwoch, 14. Juni 2023 17:48:27 CEST Thiago Macieira wrote: > On Wednesday, 14 June 2023 08:35:16 PDT Marc Mutz via Development wrote: > > >>> B) new enums MUST be scoped, also when nested in classes¹² > > >> > > >> -1 Disagree > > > > > > -1 Disagree > > > > Ok. But _why_? (Q to both) > > I'm inclined to agree with (B), so I'd like to understand the objections. As discussed earlier. Better naming in many cases until we can depend on C++20 in API. I disagree with designing API for standards we are not yet allowed to use. And there are a few rare cases with flags or other composite value types, where the implicit casting is desirable. I wouldn't mind saying scoped enums are the preferred default, and any unscoped enum needs to be justified in the commit message, but I would hate to ban them out right. Best regards Allan -- 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 Wednesday, 14 June 2023 01:52:49 PDT Marc Mutz via Development wrote: > == Why E _and_ O? == > > The reason we need E _and_ O for ordered types instead of just O is that > O needs to order the lhs w.r.t. the rhs, which generally involves > looking at all the state of the objects whereas E just needs to find > _one_ difference to be able to quickly return false. E.g., a container > can do > > bool E(~~~ lhs, ~~~ rhs) { > if (lhs.size() != rhs.size()) return false; // O cannot do this! > > } > > This is a very important optimization (and one reason why L1 string > literals are going to stay and not be replaced with UTF-8 ones: L1 op > UTF-16 _can_ use the size() short-cut while UTF-8 op UTF-16 cannot). It's also why glibc added __memcmpeq and GCC and Clang can generate a call to that. Same reason why I added QtPrivate::equalStrings() different from QtPrivate::compareStrings() (internally they call ucstreq and ucstrcmp, respectively). > == Can E be spelled op==? == > > It could. However, op== cannot have extra arguments and we have at least > one use-case where E might have an additional argument: case-insensitive > string comparisons. We currently have no (public) API to express op==, > but case-insensitively. The closest we have is QString::compare(), but > that is an O, so it cannot use the size() mismatch shortcut, assuming > it's valid for case-insensitive string comparison (it is for L1, dunno > about UTF-16). Hmm... the facts are correct but I don't think that leads to the conclusion. The whole objective here is to provide op== anyway, so the fact that some classes have this implemented in another method that can do more should be irrelevant. For those, this op== can be inline and call the out-of-line function that does the relevant work. > There's also the situation where (cheap!) implicit conversions allow one > E to backfill several different op== (which, being hidden friends, don't > participate in implicit conversions themselves). If E is spelled op==, > what would the macros use to implement op==? It would be up to the class > author to supply sufficiently-many op== in the correct form. We don't > want that. We want all op== to be generated from the macros so we have > central control over their generation (providing reversed operators in > C++17, getting the signatures right, noexcept-ness, hidden-friend-ness, > ...). They can be exceptions and written manually. However, I do not object to having the op== be an inline hidden friend, calling a private static noexcept equality comparator function (whether that's inline or not, taking extra arguments or not). In fact, I like that, purely on stylistic reasons. > == O as public API == > > In C++20, O would be spelled op<=>, but this is not possible in C++17, > so O needs to be an actual named function, not an operator. The > question, and it's a rhetorical one, then becomes: should O be public > API, and the (rhetorical) answer is "yes, because C++17 users will want > to be able to access O in C++17 projects, too (in C++20, they could call > op<=>)". This includes Qt's own implementation of O's. Side note: I think we should start compiling Qt with C++20 right now, for all compilers that support it, with no possibility for the user to turn that off. There is C++20 functionality we could use in our implementations that don't affect ABI and don't constrain C++17 users. And I also don't object to providing C++20-only features, discussed on a case-by-case basis. > Applied to our situation, this means: > > - each (orderable) class supplies O as a hidden friend > - may supply it as a (non-static) member function "At a minimum" as a hidden friend. It may be public API, like QString::compare(), whether static or non-static. > And we have the calling convention: > lhs.O(rhs); > Qt::O(lhs, rhs); // if you know the type > > using Qt::O; > O(lhs, rhs); > . // if you don't I don't think this is necessary. I would prefer if that were only allowed through op<=>. C++17-constrained users would therefore need to know the types in question, know what the "O" function is called and how to call it (static vs non- static). And if it isn't public at all, then you're limited to the traditional relational operators (op<, op<=, op> and op>=). Mind you, we're not breaking those users in any way; we're simply not adding extra API for them. Paraphrasing you about a decade ago, "C++17 costs more". > This leads to the finding that O (and, depending on the outcome of the > first two Open Questions) E cannot be named like static binary functions > in existing classes, as, even if they are semantically compatible, > they're syntactically incompatible. > > That objectively rules out "compare" for O and "equals" for E. Conclusion invalidated due to premise rejected. I couldn't follow your logic anyway, but since the premise was no longer applicable, I didn't try very hard. > ==
Re: [Development] API style guide: scoped enum or not?
> On 14 Jun 2023, at 17:48, Thiago Macieira wrote: > > On Wednesday, 14 June 2023 08:35:16 PDT Marc Mutz via Development wrote: > B) new enums MUST be scoped, also when nested in classes¹² -1 Disagree >>> >>> -1 Disagree >> >> Ok. But _why_? (Q to both) > > I'm inclined to agree with (B), so I'd like to understand the objections. This position has been explained ad nauseam. Please go back and read earlier emails in this thread. Cheers, Tor Arne -- 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)
Marc Mutz (14 June 2023 10:52) wrote: > == Naming E == > > So far, we've been using equal(). equals() doesn't work for technical > reasons, but while it'd work as a member function lhs.equals(rhs), > it's also kinda wrong if the function is taking two arguments > (equals(lhs, rhs), but there are _two_ objects). So equal() as the > plural form or equals() makes sense. No, it really doesn't (but it's illuminating to finally see why you thought it did). Sure, if we have two objects whose masses together equal that of a third, you get "equal" as the plural of "equals" but it's *still transitive* and its "those two equal this one". You can stretch to "these two equal one another" but it's severely contrived to do so; you would say "these two are equal". Besides, if you don't like areEqual(), you're really not going to welcome equalOneAnother(). I've no objection to eq() and cmp(), though, Eddy. -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On Wednesday, 14 June 2023 08:35:16 PDT Marc Mutz via Development wrote: > >>> B) new enums MUST be scoped, also when nested in classes¹² > >> > >> -1 Disagree > > > > -1 Disagree > > Ok. But _why_? (Q to both) I'm inclined to agree with (B), so I'd like to understand the objections. -- Thiago Macieira - thiago.macieira (AT) intel.com Cloud Software Architect - Intel DCAI Cloud Engineering smime.p7s Description: S/MIME cryptographic signature -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On 14.06.23 16:33, Tor Arne Vestbø via Development wrote: >> On 14 Jun 2023, at 16:20, Allan Sandfeld Jensen wrote: [...] >>> B) new enums MUST be scoped, also when nested in classes¹² >> -1 Disagree > > -1 Disagree Ok. But _why_? (Q to both) >> >>> >>> C) scoped enums SHOULD NOT repeat (part of) an enum's type name in the >>> enumerators² >>> >> +1 Agree, and if you find you do repeat the type name in an unscoped >> enum it >> probably should be scoped. But isn't this already in our style guide? > > +1 Agree, and yes, it’s already in our style guide. It's not really, no. The wording is that repeating the name isn't _necessary_. That's the kind of wording that will get a discussion going over every new enum. It should say you shouldn't repeat the name, unless there's a reason (and QML is not a reason, otherwise it's not an exception anymore). -- Marc Mutz 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
Re: [Development] API style guide: scoped enum or not?
On 14 Jun 2023, at 16:20, Allan Sandfeld Jensen wrote: On Mittwoch, 14. Juni 2023 14:59:40 CEST Marc Mutz via Development wrote: On 02.05.23 10:58, Volker Hilsheimer via Development wrote: During the header review, but also in API discussions leading up to it, we had a few cases where it would have helped if we had clearer guidelines about when to use scoped enums, and when not. Was there some consensus here? We're discussing this _again_ in the 6.6 review... Let me propose the following, separate issues, so we have something concrete to +1 or -1: [All capitalized words have the meaning of IETF RFCs] A) new enums MUST have an explicit underlying type¹² +1 Sure +1 Sure B) new enums MUST be scoped, also when nested in classes¹² -1 Disagree -1 Disagree C) scoped enums SHOULD NOT repeat (part of) an enum's type name in the enumerators² +1 Agree, and if you find you do repeat the type name in an unscoped enum it probably should be scoped. But isn't this already in our style guide? +1 Agree, and yes, it’s already in our style guide. Cheers, Tor Arne -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On Mittwoch, 14. Juni 2023 14:59:40 CEST Marc Mutz via Development wrote: > On 02.05.23 10:58, Volker Hilsheimer via Development wrote: > > During the header review, but also in API discussions leading up to it, we > > had a few cases where it would have helped if we had clearer guidelines > > about when to use scoped enums, and when not. > Was there some consensus here? We're discussing this _again_ in the 6.6 > review... > > Let me propose the following, separate issues, so we have something > concrete to +1 or -1: > > [All capitalized words have the meaning of IETF RFCs] > > A) new enums MUST have an explicit underlying type¹² +1 Sure > > B) new enums MUST be scoped, also when nested in classes¹² -1 Disagree > > C) scoped enums SHOULD NOT repeat (part of) an enum's type name in the > enumerators² > +1 Agree, and if you find you do repeat the type name in an unscoped enum it probably should be scoped. But isn't this already in our style guide? Best regards Allan -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] API style guide: scoped enum or not?
On 02.05.23 10:58, Volker Hilsheimer via Development wrote: > During the header review, but also in API discussions leading up to it, we > had a few cases where it would have helped if we had clearer guidelines about > when to use scoped enums, and when not. Was there some consensus here? We're discussing this _again_ in the 6.6 review... Let me propose the following, separate issues, so we have something concrete to +1 or -1: [All capitalized words have the meaning of IETF RFCs] A) new enums MUST have an explicit underlying type¹² For unscoped enums, the compiler otherwise picks one, possibly resulting in BiC when new addtions change the underlying type or otherwise just warnings because one compiler uses a signed and the other an unsigned type (most recent exmaple: QTBUG-113792). For scoped enums, the type is int, but probably not always, and why require the reader of the code to know the C++ rules when we can make it explicit? B) new enums MUST be scoped, also when nested in classes¹² Type safety > verbosity. Qt has never preferred brevity over verbosity when it comes to readability, and while the use of short identifiers makes code often more readable than using long ones, C++20's `using enum` feature empowers users to choose between brevity and verbosity on a per-use basis. Since we should be designing for the future and not the past, this removes the major objection for scoped enums. C++17 doesn't matter. If we really want leaking, we can use constexpr variables of scoped enum type in lieu of enumerators. C) scoped enums SHOULD NOT repeat (part of) an enum's type name in the enumerators² This was a work-around from the times of C/C++98 when you could neither scope the value of an enumeration nor prevent the leakage of enumerator names into the enclosing scope. We have both now in C++11: any enumerator can be scoped and scoped enums don't leak the name into the enclosing scope anymore. I cannot rule out that sometimes some part of the enum's type may make sense in an enumerator's name, but not consistently in all of them just because one of them needs it etc, so this is a SHOULD, not a MUST. I have been told today that QML allows scoped C++ enums to be used without the scope. If this is true, it should be fixed to always require the scope, because otherwise the argument goes "but in QML, the scope isn't visible, so a part of the enum type name must be included in the enumerators". ¹ except when C compatibility is required ² applies to all enums come Qt 7 It would be good if we could have clarity on A-C before we finish up the 6.6 API review. Thanks, Marc -- Marc Mutz 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
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
On 03.11.22 10:40, Marc Mutz via Development wrote: > TL;DR: provide named functions for the minimal set of op== and op<=> > we'd have to write in C++20, then use macros to turn these into op==, > op!=, op<, op>, op<=, op>= for C++17 builds and op== and op<=> for C++20 > builds. This part somehow became lost and kinda made the whole feature miss the 6.6 train, so let me expand on it a bit, and collect open questions (marked with → below): We want the implementation of these relational operators be as close as possible to the way C++20 will work: There, you implement op== and op<=> and the compiler synthesizes everything else (cf. parent message for details). So we need one function E backing op== and, for ordered types, another function O backing op<=>. == Why E _and_ O? == The reason we need E _and_ O for ordered types instead of just O is that O needs to order the lhs w.r.t. the rhs, which generally involves looking at all the state of the objects whereas E just needs to find _one_ difference to be able to quickly return false. E.g., a container can do bool E(~~~ lhs, ~~~ rhs) { if (lhs.size() != rhs.size()) return false; // O cannot do this! } This is a very important optimization (and one reason why L1 string literals are going to stay and not be replaced with UTF-8 ones: L1 op UTF-16 _can_ use the size() short-cut while UTF-8 op UTF-16 cannot). == Can E be spelled op==? == It could. However, op== cannot have extra arguments and we have at least one use-case where E might have an additional argument: case-insensitive string comparisons. We currently have no (public) API to express op==, but case-insensitively. The closest we have is QString::compare(), but that is an O, so it cannot use the size() mismatch shortcut, assuming it's valid for case-insensitive string comparison (it is for L1, dunno about UTF-16). So there's a certain appeal in using E as a way to consistently spell "op== with extra arguments". We could, e.g. do E(lhs, rhs, Qt::FuzzyComparison) for anything involving FP. There's also the situation where (cheap!) implicit conversions allow one E to backfill several different op== (which, being hidden friends, don't participate in implicit conversions themselves). If E is spelled op==, what would the macros use to implement op==? It would be up to the class author to supply sufficiently-many op== in the correct form. We don't want that. We want all op== to be generated from the macros so we have central control over their generation (providing reversed operators in C++17, getting the signatures right, noexcept-ness, hidden-friend-ness, ...). So I would require new information to accept anything than a "no" here: → Semi-Open question 1: Should E be spelled op==? My take is no. → Open question 2: Should E exist for all types, as a "concept name" for "op== with parameters", or should we leave that, as it is now, on type-by-type basis to each class author individually? My take is that yes, it should exist as a "concept name". I added qStringsEqual() in 5.10 as public API when adding QStringView, but it was relegated to private API before the release. When class authors are given the option to accept parameters for equality comparison, they will find novel ways to use it (like Qt::Fuzzy). == O as public API == In C++20, O would be spelled op<=>, but this is not possible in C++17, so O needs to be an actual named function, not an operator. The question, and it's a rhetorical one, then becomes: should O be public API, and the (rhetorical) answer is "yes, because C++17 users will want to be able to access O in C++17 projects, too (in C++20, they could call op<=>)". This includes Qt's own implementation of O's. The gold standard for named operators in C++ is to have the implementation as a hidden friend (think swap()), possibly a member function (lhs.swap(rhs)), a (namespaced) fallback version for built-in types (std::swap(int, int)) and a calling convention that takes this into account: lhs.swap(rhs); // or std::swap(lhs, rhs); // if you know decltype(lhs), ... using std::swap; swap(lhs, rhs); // or std::ranges::swap(lhs, rhs); // ... if you don't. Applied to our situation, this means: - each (orderable) class supplies O as a hidden friend - may supply it as a (non-static) member function - Qt provides an implementation for built-in types in a namespace (we only have 'Qt'). And we have the calling convention: lhs.O(rhs); Qt::O(lhs, rhs); // if you know the type using Qt::O; O(lhs, rhs); O_as_CPO(lhs, rhs); // if you don't O_as_CPO is to O what std::ranges::swap is to swapping: an ADL-enabled version that allows to skip the using Qt::O/using std::swap; The same would be applicable to E if Open Question 1 ends up resolved as no and Open Question 2 as "yes, named concept". This leads to the finding that O (and, depending on the outcome of the first
[Development] Heads-up: what's new in '6.6' doc needs your updates
Hi all, https://code.qt.io/cgit/qt/qtdoc.git/tree/doc/src/whatsnew/whatsnew66.qdoc seems to be quite unfinished ☹ It would be good to get some more content there for Qt 6.6 Beta1 (which is planned to happen during this week). So please do at least most important updates now; finalizing and polishing can then happen later in beta phase. br, Jani -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] C++20 ctor-level [[nodiscard]] (was: Re: C++20 @ Qt)
Hi, TL;DR: - we should add Q_DISCARD_CTOR to all ctors of classes with class-level [[nodiscard]], esp. RAII objects - class-level [[nodiscard]] seems to be abused atm to get ctor-level [[nodiscard]] semantics in C++!7 - do we want to mark (almost) all ctors as [[nodiscard]], in the future? Long form: Ivan implemented Q_NODISCARD_CTOR for 6.6 and I've started to roll use of it our over the QtBase. I have some questions. First, some terms: I call this a class-level [[nodicard]]: class [[nodiscard]] QSignalBlocker { }; This is a C++17 feature and we can (and do) use it unconditionally. I call this a ctor-level [[nodiscard]]: class QSignalBlocker { public: [[nodiscard]] explicit QSignalBlocker(QObject *o) ; }; This is a C++20 feature (technically, it's a clarification, potentially retroactively applied to C++!7, but that still means we can't rely on it), which is why we need a macro. I won't lecture about what the two so, you can read up on that on cppreference.com: - https://en.cppreference.com/w/cpp/language/attributes/nodiscard - Paper: wg21.link/p1771 The obvious first scenario is to cause warnings for code such as // Listing 1 QMutexLocker(); Or any other RAII class. Clang warns about this with a class-level [[nodiscard]]. GCC does not. So the first rule should be to make all ctors [[nodiscard]] in classes that are class-level [[nodiscard]]. So far so good. Enter QScopedPointer. It currently has a class-level [[nodiscard]], but does that actually make sense? C++!7 allows us to return QScopedPointer from a function (guaranteed copy elision), so users can write functions that return QScopedPointer. But it's not like use of that return value is required to be required. So I've come to think that this use of class-level [[nodiscard]] is wrong. It's the only way to get the desired warning for Listing 1 in C++17 (absent P1771), on some compilers, but the semantics are wrong. Even for pure RAII types: I might return a QMutexLocker from a function, but that shouldn't mean that function's return value is [[nodiscard]]. It might be perfectly ok to discard it. We don't know, yet we enforce that policy for everyone by making QMutexLocker class-level [[nodiscard]]. In fact, what we actually want is ctor-level [[nodiscard]] in these cases. For the time being, given we support C++17, I'm ok with having class-level [[nodiscard]] on pure RAII classes (ie. not on smart pointers), but come C++20, we should remove these in favour of ctor-level [[nodiscard]]s. Here comes the can of worms: If you accept that Listing 1 is worth warning about, what about // Listing 2 QSize(12, 32); // Listing 3 QString("Hello, useless"); // Listing 4 QSlider(0, 100, this); Does this mean that, like for most const member functions that have since gotten [[nodiscard]] because their only side-effect is to produce a return value, we should mark _all_ ctors [[nodiscard]], because their only side-effect is to produce an object? Thanks, Marc -- Marc Mutz 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