> On 5 Nov 2025, at 19:07, Ville Voutilainen <[email protected]> > wrote: > > On Wed, 5 Nov 2025 at 14:05, Volker Hilsheimer <[email protected]> > wrote: >> >> >> >>> On 5 Nov 2025, at 12:30, Ville Voutilainen <[email protected]> >>> wrote: >>> >>> On Wed, 5 Nov 2025 at 12:11, Volker Hilsheimer via Development >>> <[email protected]> wrote: >>>> And again, we need to make sure that object->createChild<QWidget>() is not >>>> possible; from what I see, that can be solved via SFINAE: >>>> >>>> class QObject … >>>> { >>>> template <typename ChildType, typename ...Args, >>>> std::enable_if_t<!std::is_base_of_v<QWidget, ChildType>, bool> >>>> = true >>>>> >>>> ChildType *makeChild(Args &&...args) >>>> { >>>> return new ChildType(std::forward<Args>(args)..., this); >>>> } >>>> }; >>>> >>>> (it’s enough for QWidget to be forward declared, which it is already in >>>> qobject.h) >>>> >>>> and then overloading this in QWidget without the constraint (a QObject can >>>> be a child of a QWidget). >>> >>> I don't quite follow why you think you need any SFINAE for this. If >>> you try to construct a QWidget child with a >>> QObject::createChildObject(), >>> that will fail to compile anyway because it tries to pass a QObject* >>> parent to the QWidget constructor, and that >>> constructor takes a QWidget*. There is no implicit base*->derived* >>> conversion. >> >> >> “fails to compile” != “fails to compile and produces a meaningful error >> message” >> >> >> Without SFINAE: >> >> /Users/vohi/qt/dev/qtbase/src/corelib/kernel/qobject.h:354:20: error: no >> matching constructor for initialization of 'QLineEdit' >> 354 | return new ChildType(std::forward<Args>(args)..., this); >> | ^ ~~~~ >> /Users/vohi/qt/dev/qtbase/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp:14209:12: >> note: in instantiation of function template specialization >> 'QObject::makeChild<QLineEdit>' requested here >> 14209 | object.makeChild<QLineEdit>(); >> | ^ >> /Users/vohi/qt/dev/qtbase/src/widgets/widgets/qlineedit.h:58:14: note: >> candidate constructor not viable: cannot convert from base class pointer >> 'QObject *' to derived class pointer 'QWidget *' for 1st argument >> 58 | explicit QLineEdit(QWidget *parent = nullptr); > > Right, here. > >> | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ >> /Users/vohi/qt/dev/qtbase/src/widgets/widgets/qlineedit.h:59:14: note: >> candidate constructor not viable: no known conversion from 'QObject *' to >> 'const QString' for 1st argument >> 59 | explicit QLineEdit(const QString &, QWidget *parent = nullptr); >> | ^ ~~~~~~~~~~~~~~~ >> /Users/vohi/qt/dev/qtbase/src/widgets/widgets/qlineedit.h:216:20: note: >> candidate constructor not viable: no known conversion from 'QObject *' to >> 'const QLineEdit' for 1st argument >> 216 | Q_DISABLE_COPY(QLineEdit) >> | ~~~~~~~~~~~~~~~^~~~~~~~~~ >> /Users/vohi/qt/dev/qtbase/src/corelib/global/qtclasshelpermacros.h:24:5: >> note: expanded from macro 'Q_DISABLE_COPY' >> 24 | Class(const Class &) = delete;\ >> | ^ ~~~~~~~~~~~~~ >> 1 error generated. >> ninja: build stopped: subcommand failed. >> >> >> (probably multiplied by number of constructors of the ChildType you wanna >> instantiate, as the compiler will try each of them). >> >> >> With SFINAE: >> >> /Users/vohi/qt/dev/qtbase/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp:14209:12: >> error: no matching member function for call to 'makeChild' >> 14209 | object.makeChild<QLineEdit>(); >> | ~~~~~~~^~~~~~~~~~~~~~~~~~~~ >> /Users/vohi/qt/dev/qtbase/src/corelib/kernel/qobject.h:354:16: note: >> candidate template ignored: requirement '!std::is_base_of_v<QWidget, >> QLineEdit>' was not satisfied [with ChildType = QLineEdit, Args = <>] >> 354 | ChildType *makeChild(Args &&...args) > > Do you expect to SFINAE away also QWindow and QGraphicsItem and other > types, too? > > Why use an enable_if instead of static_assert?
As the mailing list doesn’t make for a great code review experience: https://codereview.qt-project.org/c/qt/qtbase/+/689322 Good catch with QWindow (and possibly other types for which we explictly overload setParent to require something else than QObject *); QGraphicsItem is not a QObject. Cheers, Volker -- Development mailing list [email protected] https://lists.qt-project.org/listinfo/development
