Ville Voutilainen <[email protected]> schrieb am Di., 4. Nov. 2025, 21:05:
> On Tue, 4 Nov 2025 at 13:07, Daniel Schürmann <[email protected]> wrote: > > 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? > > Sure, it makes sense to postpone the idea of such a universal thing. > > But while doing that, I think it continues to make perfect sense to > have a less-universal version of it. > > new Child(parent); > > looks very weird, and > > parent->createChildObject<Child>(); > > would be quite an improvement. > > And QParentedPointer can still be universal, because it would just > assert the same p->parent() for multiple > different types, even if those parents are of different types. > Hi Ville Yes, the whole initiative starts for hiding "new Child(parent);" Without knowing the internals of Child, readers and linter tools don't know whether it returns an owning pointer or a borrowed pointer. I have these requirements in mind: * offer a one stop solution that works for all QObject based classes, that allows to refactor all these plain new() calls out of a project in one go. * Zero runtime overhead. * Automatic refactoring suggestions by clazy I already have a working solution for QObject, that allows us to omit the parent argument in the constructor args as discussed (See below). With c++23 it can be made universal. 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. What are the alternatives? parent->createChildObject<Child>(arg1, arg2, parent); pro: * has the parent as "this" pointer * constructor arguments remain, less typo risk during a mass refactoring m_child = new Child (arg1, arg2, arg3); m_child = arg3->createChildObject<Child>(arg1, arg2, arg3); contra: * Still a typo risk because the user needs to do the "parent->" part correct * redundant parent * clazy needs to know what the parent is. This trade does not convince me. What are your ideas? Best regards Daniel template<typename T, typename... Args> T *createChild(Args&&... args) { static_assert(std::is_base_of_v<QObject, T>, "makeChild<T>: T must inherit QObject"); T *child = nullptr; // Fist try to append 'this' as: T(args..., QObject*) this will work for // all QObject based calsses with an optional parent pointer as the // last constructor parameter T(.., QObject *parent = nullptr) if constexpr (std::is_constructible_v<T, Args&&..., QObject*>) { child = new T(std::forward<Args>(args)..., this); } // QWidget has the parent fist else if constexpr (std::is_constructible_v<T, QObject*, Args&&...>) { child = new T(this, std::forward<Args>(args)...); } // Finally pass forward args unchanged else if constexpr (std::is_constructible_v<T, Args&&...>) { child = new T(std::forward<Args>(args)...); } else { static_assert(sizeof(T) == 0, "QObject::makeChild: no matching constructor found for T with provided arguments"); } Q_ASSERT(child->parent() == this); return child; }
-- Development mailing list [email protected] https://lists.qt-project.org/listinfo/development
