[Development] parented_ptr

Volker Hilsheimer volker.hilsheimer at qt.io
Wed Nov 5 11:09:42 CET 2025



> On 5 Nov 2025, at 09:32, André Somers via Development <development at qt-project.org> wrote:
> 
> 
> On 05-11-2025 09:10, Arno Rehn wrote:
>> On 05.11.2025 08:22, Daniel Schürmann wrote:
>>> However I am not confident that this bullet proved enough for being integrated in the upstream library.
>>> * It works by guessing the parent argument which can fail at runtime without even a compiler message, in users code.
>>> * It does not yet (<x++23) support constructors requiring a sub class parent like QWidget or any other user defined sub class.
>>> * We can make it more robust by constructing without parent and then call setParent() causing some extra calls and bookkeeping. I don't want that.
>> 
>> Honestly I think you're over-engineering this somewhat. "parent comes last" is an established convention when dealing with QObject-derived classes. QWidgets are the same, see for example QPushButton:
>> 
>>     QPushButton(const QIcon &icon, const QString &text, QWidget *parent)
>> 
>> Just forward the args and append "this" as the last parameter to pass the parent along.
> 
> Problem is, I guess, that while it is a convention, it is not true 100% of the time. Not even in Qt. See QWidget for instance as a counterexample:
> 
>     [explicit] QWidget::QWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
> 
> For customer code, you can't be sure people followed this convention at all of course.
> 
>> 
>> Re subclass parents: You don't actually need C++23 for that. We can (ab-)use a templated implicit conversion operator to auto-cast a type to the one required by the constructor:
> 
> Wow... that looks... dirty. My kind of dirty trick.
> 
> Cheers,
> 
> André


Even QWidget can be created with the parent pointer as the last argument, as the flags argument is optional.

The limitation here is rather that createChild<QWidget> cannot be used to create a child widget with window flags. That’s acceptable - the flags can be set after the fact as well.

Not being able to create types that have no suitable constructor is an acceptable, documentable, and static_assert’able limitation. We could even fall back to an explicit “newChild->setParent(this)” call after constructing the child type without parent argument.

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).

Volker



More information about the Development mailing list