[Development] parented_ptr
Daniel Schürmann
daschuer at mixxx.org
Tue Nov 4 12:07:32 CET 2025
On Tue, Nov 4, 2025 at 11:45 AM Ville Voutilainen <
ville.voutilainen at gmail.com> wrote:
> 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.
>
I agree, we should encourage users to create childs with valid parents.
That's what
QParentedPointer<T> implies and asserts in debug mode.
>From my experience in all code, it is possible to refactor for instance
widget creation to bottom up.
This allows to use QParentedPointer<T> and removes the need for addChild.
An addChild will encourage people to refactor it towards a unique_ptr,
which is not the best solution.
It is probably better to keep the code untouched in that case.
I have originally picked up the idea from this thread, but I am fine to
drop it for now.
The discussed topic around this deduction applies unfortunately for
createChild() as well.
I have now, just for hiding new():
template <class T, typename... Args>
QParentedPointer<T> qCreateParented(Args &&...args)
{
static_assert(!std::is_pointer<T>::value,
"qCreateParented's template type must not be a pointer
type");
static_assert(std::is_base_of_v<QObject, T>,
"qCreateParented's template type must inherit QObject");
return QParentedPointer<T>(new T(std::forward<Args>(args)...));
}
for:
qCreateParented<QLabel>(parent);
if you want an universal:
parent->createChild<QLabel>();
It is possible with C++23 and if we assume that either the fist or the last
parameter is the parent.
Quite cumbersome. I would like to postpone this for now.
Does that make sense?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20251104/0f5b7edf/attachment.htm>
More information about the Development
mailing list