diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2021-07-08 09:41:53 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2021-07-12 15:16:11 +0000 |
commit | 35528215515c880625d22e616514f02e59d61b2d (patch) | |
tree | b981fc8eb34ccd39d374fd69082b824a345d84de /src/corelib/kernel/qobject.h | |
parent | 505bdd07c03712194f776718d2516a388c6d44ea (diff) |
QObject: make new-style-connects SFINAE-friendly
SFINAE out the new-style connect() overloads for const char*
functions.
Before, we detected the problem in the body of connect(), by failing
the static_assert for signal/slot argument compatibility, but that's
too late. We don't want to select that overload at all, because we
want that decltype(QObject::connect(QAction*, &QAction::triggered,
QObject*, SLOT(something())) SFINAEs instead of returning
QMetaObject::Connect, because then all the classes that provide
convenience new-style connect syntax by wrapping the
QObject::connect() call can just use that decltype() to accept
anything that will succeed in the wrapped connect() call instead of
manually trying (and failing) to provide proper overloads themselves.
[ChangeLog][QtCore][Potentially Source-Incompatible Changes]
QObject::connect(sender, pointer-to-member, [receiver, ], SLOT(~~~))
is now SFINAEd out instead of triggering a static_assert(). That means
it is now possible to use Expression SFINAE
(decltype(QObject::connect(<sender>, <signal>,
std::declval<Args>()...) to properly wrap new-style QObject::connect()
calls with a single wrapper function, greatly simplifying the
implementation, incl. passing Qt::ConnectionType arguments. For more
information on how to use this in your own code, see the sources of
QWidget::addAction().
Change-Id: I4052a49eacd63a432a9648a667adc435744a633d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/kernel/qobject.h')
-rw-r--r-- | src/corelib/kernel/qobject.h | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 6f5d574f70..6a8088ef12 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -285,7 +285,10 @@ public: //connect to a functor template <typename Func1, typename Func2> - static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type + static inline typename std::enable_if< + QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1 && + !std::is_convertible_v<Func2, const char*>, // don't match old-style connect + QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot) { return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection); @@ -293,7 +296,10 @@ public: //connect to a functor, with a "context" object defining in which event loop is going to be executed template <typename Func1, typename Func2> - static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type + static inline typename std::enable_if< + QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1 && + !std::is_convertible_v<Func2, const char*>, // don't match old-style connect + QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { |