[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