[Development] parented_ptr

Ville Voutilainen ville.voutilainen at gmail.com
Tue Nov 4 11:44:57 CET 2025


On Mon, 3 Nov 2025 at 20:13, Daniel Schürmann <daschuer at mixxx.org> wrote:
>
> On Mon, Nov 3, 2025 at 4:59 PM Ville Voutilainen <ville.voutilainen at gmail.com> wrote:
>>
>> On Mon, 3 Nov 2025 at 17:52, Ville Voutilainen
>> <ville.voutilainen at gmail.com> wrote:
>> > > the workaround is the rather ugly:
>> > >
>> > > parent.createChild<QObject>(&parent);
>> >
>> > That's not needed at all.
>>
>> See, the reason is that QObject parents aren't of type
>> SomeTypeInheritingQObject. They are QObjects.
>>
>> That's why we don't need to deduce the parent type (which we can do
>> since C++23, but we don't need to go to that here),
>> and QObject works for the parent type.
>>
>> Same goes for QWidgets.
>>
>> You can of course pass whatever derived type pointer as the parent
>> argument, it will just get implicitly converted to a pointer
>> to the base type.
>
>
>
> QObject does not work as an universal parent type. This works only for lifetime management.

Yes, and lifetime management cases are exactly the ones that
createChildObject() needs to support,
and it doesn't need to support anything else.

> There are a couple of overloads for setParent that require a different type to tie some other ends.

That suggests that those hierarchies should have their own
createChildWhatever(), not that we
should try to have a universal createChild(). See at the end.

> Adding a function that takes an unexpected overload of a base class is a source of headaches.
>
> A Quick search reveals ~10 different overloads in qtbase alone like:
>
> void QWindow::setParent(QWindow *parent)

You don't need to create a QWindow with createChildObject(). Create it
with std::make_unique().
Or add a createChildWindow(). See at the end.

> Thank you for the hint that this pointer deducing is a C++23 feature. Now I have found it we can do:
>
>
> class QObject {
> public:
>     template <typename Self, typename T>
>     QParentedPointer<T> addChild(this Self&& self, std::unique_ptr<T> child)
>     {
>         Q_ASSERT(child);
>         child->setParent(&self);
>         return QParentedPointer<T>(std::move(child));
>     }
> }
>
> This works for all of them (not tested)
> Do you see a chance to add that with a C++23 guard?

I don't think we should strive for an API that requires separate steps
for creating a child and setting its
parent, I think it's better if our API (and how it works internally)
just creates children with a parent argument.
There's all kinds of types in Qt that end up doing a whole lot of
pointless work if they're first created without
a parent and then separately reparented.


More information about the Development mailing list