[Development] parented_ptr

Volker Hilsheimer volker.hilsheimer at qt.io
Wed Nov 5 13:05:49 CET 2025



> On 5 Nov 2025, at 12:30, Ville Voutilainen <ville.voutilainen at gmail.com> wrote:
> 
> On Wed, 5 Nov 2025 at 12:11, Volker Hilsheimer via Development
> <development at qt-project.org> 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);
      |              ^         ~~~~~~~~~~~~~~~~~~~~~~~~~
/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)

Volker



More information about the Development mailing list