summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Kümmel <syntheticpp@gmx.net>2015-11-10 18:57:40 +0100
committerOlivier Goffart (Woboq GmbH) <ogoffart@woboq.com>2016-02-15 12:33:24 +0000
commitab8cc8387f1891ccf99721bfe5a6182c507e332f (patch)
treea892939a744e2fa65dba687f0f42e293b45963f5
parente41e0346698c4578da4625ef3cce7f5417b71e08 (diff)
Add qOverload to select overloaded functions
[ChangeLog][QtCore][Global] qOverload added to select overloaded functions. Change-Id: I7c9b1b054e6631eca0b5594db59e1202ef552c33 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp23
-rw-r--r--src/corelib/global/qglobal.cpp43
-rw-r--r--src/corelib/global/qglobal.h60
-rw-r--r--src/corelib/kernel/qobject.cpp6
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp122
5 files changed, 254 insertions, 0 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index ccf8399e0d..ba02f75963 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -568,6 +568,29 @@ struct A : public B {
template<> class QTypeInfo<A> : public QTypeInfoMerger<A, B, C, D> {};
//! [51]
+//! [52]
+ struct Foo {
+ void overloadedFunction();
+ void overloadedFunction(int, QString);
+ };
+ ... qOverload<>(&Foo:overloadedFunction)
+ ... qOverload<int, QString>(&Foo:overloadedFunction)
+//! [52]
+
+//! [53]
+ ... QOverload<>::of(&Foo:overloadedFunction)
+ ... QOverload<int, QString>::of(&Foo:overloadedFunction)
+//! [53]
+
+//! [54]
+ struct Foo {
+ void overloadedFunction(int, QString);
+ void overloadedFunction(int, QString) const;
+ };
+ ... qConstOverload<>(&Foo:overloadedFunction)
+ ... qNonConstOverload<int, QString>(&Foo:overloadedFunction)
+//! [54]
+
//! [qlikely]
// the condition inside the "if" will be successful most of the times
for (int i = 1; i <= 365; i++) {
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index a7ed29d859..e4fa0f7391 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -921,6 +921,49 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in
\sa qMin(), qMax()
*/
+/*! \fn auto qOverload(T functionPointer)
+ \relates <QtGlobal>
+ \since 5.7
+
+ qOverload() returns a pointer to an overloaded function. The template
+ parameter is the list of the argument types of the function.
+ \a functionPointer is the pointer to the (member) function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 52
+
+ If a member function is also const-overladed \l qConstOverload and
+ \l qNonConstOverload needs to be used.
+
+ qOverload() needs C++14 enabled. In C++11 only code the helper
+ classes QOverload, QConstOverload, and QNonConstOverload could be used directly:
+
+ \snippet code/src_corelib_global_qglobal.cpp 53
+
+ \sa qConstOverload(), qNonConstOverload()
+*/
+
+/*! \fn auto qConstOverload(T memberFunctionPointer)
+ \relates <QtGlobal>
+ \since 5.7
+
+ qConstOverload() returns a pointer to an constant member function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 54
+
+ \sa qOverload, qNonConstOverload
+*/
+
+/*! \fn auto qNonConstOverload(T memberFunctionPointer)
+ \relates <QtGlobal>
+ \since 5.7
+
+ qNonConstOverload() eturns a pointer to an non constant member function:
+
+ \snippet code/src_corelib_global_qglobal.cpp 54
+
+ \sa qOverload, qNonConstOverload
+*/
+
/*!
\macro QT_VERSION_CHECK
\relates <QtGlobal>
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 69840996dc..d607b04192 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1018,6 +1018,66 @@ Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1);
{ return T::dynamic_cast_will_always_fail_because_rtti_is_disabled; }
#endif
+
+#ifdef Q_QDOC
+
+// Just for documentation generation
+auto qOverload(T functionPointer);
+auto qConstOverload(T memberFunctionPointer);
+auto qNonConstOverload(T memberFunctionPointer);
+
+#elif defined(Q_COMPILER_VARIADIC_TEMPLATES)
+
+template <typename... Args>
+struct QNonConstOverload
+{
+ template <typename R, typename T>
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QConstOverload
+{
+ template <typename R, typename T>
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R, typename T>
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+};
+
+template <typename... Args>
+struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
+{
+ using QConstOverload<Args...>::of;
+ using QConstOverload<Args...>::operator();
+ using QNonConstOverload<Args...>::of;
+ using QNonConstOverload<Args...>::operator();
+
+ template <typename R>
+ Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+
+ template <typename R>
+ static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+ { return ptr; }
+};
+
+#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 // C++14
+template <typename... Args> Q_CONSTEXPR QOverload<Args...> qOverload Q_DECL_UNUSED = {};
+template <typename... Args> Q_CONSTEXPR QConstOverload<Args...> qConstOverload Q_DECL_UNUSED = {};
+template <typename... Args> Q_CONSTEXPR QNonConstOverload<Args...> qNonConstOverload Q_DECL_UNUSED = {};
+#endif
+
+#endif
+
+
class QByteArray;
Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index dea8c200ef..6702f78a04 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -4538,6 +4538,8 @@ void qDeleteInEventHandler(QObject *o)
make sure to declare the argument type with Q_DECLARE_METATYPE
+ Overloaded functions can be resolved with help of \l qOverload.
+
\note The number of arguments in the signal or slot are limited to 6 if
the compiler does not support C++11 variadic templates.
*/
@@ -4573,6 +4575,8 @@ void qDeleteInEventHandler(QObject *o)
However, you should take care that any objects used within the functor
are still alive when the signal is emitted.
+ Overloaded functions can be resolved with help of \l qOverload.
+
\note If the compiler does not support C++11 variadic templates, the number
of arguments in the signal or slot are limited to 6, and the functor object
must not have an overloaded or templated operator().
@@ -4612,6 +4616,8 @@ void qDeleteInEventHandler(QObject *o)
However, you should take care that any objects used within the functor
are still alive when the signal is emitted.
+ Overloaded functions can be resolved with help of \l qOverload.
+
\note If the compiler does not support C++11 variadic templates, the number
of arguments in the signal or slot are limited to 6, and the functor object
must not have an overloaded or templated operator().
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index d1a6e66203..152906287c 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -55,6 +55,7 @@ private slots:
void qprintable();
void qprintable_data();
void buildAbiEndianness();
+ void testqOverload();
};
void tst_QGlobal::qIsNull()
@@ -652,5 +653,126 @@ void tst_QGlobal::buildAbiEndianness()
QVERIFY(QSysInfo::buildAbi().contains(endian));
}
+struct Overloaded
+{
+ void foo() {}
+ void foo(QByteArray) {}
+ void foo(QByteArray, const QString &) {}
+
+ void constFoo() const {}
+ void constFoo(QByteArray) const {}
+ void constFoo(QByteArray, const QString &) const {}
+
+ void mixedFoo() {}
+ void mixedFoo(QByteArray) const {}
+};
+
+void freeOverloaded() {}
+void freeOverloaded(QByteArray) {}
+void freeOverloaded(QByteArray, const QString &) {}
+
+void freeOverloadedGet(QByteArray) {}
+QByteArray freeOverloadedGet() { return QByteArray(); }
+
+
+void tst_QGlobal::testqOverload()
+{
+#ifdef Q_COMPILER_VARIADIC_TEMPLATES
+
+ // void returning free overloaded functions
+ QVERIFY(QOverload<>::of(&freeOverloaded) ==
+ static_cast<void (*)()>(&freeOverloaded));
+
+ QVERIFY(QOverload<QByteArray>::of(&freeOverloaded) ==
+ static_cast<void (*)(QByteArray)>(&freeOverloaded));
+
+ QVERIFY((QOverload<QByteArray, const QString &>::of(&freeOverloaded)) ==
+ static_cast<void (*)(QByteArray, const QString &)>(&freeOverloaded));
+
+ // value returning free overloaded functions
+ QVERIFY(QOverload<>::of(&freeOverloadedGet) ==
+ static_cast<QByteArray (*)()>(&freeOverloadedGet));
+
+ QVERIFY(QOverload<QByteArray>::of(&freeOverloadedGet) ==
+ static_cast<void (*)(QByteArray)>(&freeOverloadedGet));
+
+ // void returning overloaded member functions
+ QVERIFY(QOverload<>::of(&Overloaded::foo) ==
+ static_cast<void (Overloaded::*)()>(&Overloaded::foo));
+
+ QVERIFY(QOverload<QByteArray>::of(&Overloaded::foo) ==
+ static_cast<void (Overloaded::*)(QByteArray)>(&Overloaded::foo));
+
+ QVERIFY((QOverload<QByteArray, const QString &>::of(&Overloaded::foo)) ==
+ static_cast<void (Overloaded::*)(QByteArray, const QString &)>(&Overloaded::foo));
+
+ // void returning overloaded const member functions
+ QVERIFY(QOverload<>::of(&Overloaded::constFoo) ==
+ static_cast<void (Overloaded::*)() const>(&Overloaded::constFoo));
+
+ QVERIFY(QOverload<QByteArray>::of(&Overloaded::constFoo) ==
+ static_cast<void (Overloaded::*)(QByteArray) const>(&Overloaded::constFoo));
+
+ QVERIFY((QOverload<QByteArray, const QString &>::of(&Overloaded::constFoo)) ==
+ static_cast<void (Overloaded::*)(QByteArray, const QString &) const>(&Overloaded::constFoo));
+
+ // void returning overloaded const AND non-const member functions
+ QVERIFY(QNonConstOverload<>::of(&Overloaded::mixedFoo) ==
+ static_cast<void (Overloaded::*)()>(&Overloaded::mixedFoo));
+
+ QVERIFY(QConstOverload<QByteArray>::of(&Overloaded::mixedFoo) ==
+ static_cast<void (Overloaded::*)(QByteArray) const>(&Overloaded::mixedFoo));
+
+#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 // C++14
+
+ // void returning free overloaded functions
+ QVERIFY(qOverload<>(&freeOverloaded) ==
+ static_cast<void (*)()>(&freeOverloaded));
+
+ QVERIFY(qOverload<QByteArray>(&freeOverloaded) ==
+ static_cast<void (*)(QByteArray)>(&freeOverloaded));
+
+ QVERIFY((qOverload<QByteArray, const QString &>(&freeOverloaded)),
+ static_cast<void (*)(QByteArray, const QString &)>(&freeOverloaded));
+
+ // value returning free overloaded functions
+ QVERIFY(qOverload<>(&freeOverloadedGet) ==
+ static_cast<QByteArray (*)()>(&freeOverloadedGet));
+
+ QVERIFY(qOverload<QByteArray>(&freeOverloadedGet) ==
+ static_cast<void (*)(QByteArray)>(&freeOverloadedGet));
+
+ // void returning overloaded member functions
+ QVERIFY(qOverload<>(&Overloaded::foo) ==
+ static_cast<void (Overloaded::*)()>(&Overloaded::foo));
+
+ QVERIFY(qOverload<QByteArray>(&Overloaded::foo) ==
+ static_cast<void (Overloaded::*)(QByteArray)>(&Overloaded::foo));
+
+ QVERIFY((qOverload<QByteArray, const QString &>(&Overloaded::foo)) ==
+ static_cast<void (Overloaded::*)(QByteArray, const QString &)>(&Overloaded::foo));
+
+ // void returning overloaded const member functions
+ QVERIFY(qOverload<>(&Overloaded::constFoo) ==
+ static_cast<void (Overloaded::*)() const>(&Overloaded::constFoo));
+
+ QVERIFY(qOverload<QByteArray>(&Overloaded::constFoo) ==
+ static_cast<void (Overloaded::*)(QByteArray) const>(&Overloaded::constFoo));
+
+ QVERIFY((qOverload<QByteArray, const QString &>(&Overloaded::constFoo)) ==
+ static_cast<void (Overloaded::*)(QByteArray, const QString &) const>(&Overloaded::constFoo));
+
+ // void returning overloaded const AND non-const member functions
+ QVERIFY(qNonConstOverload<>(&Overloaded::mixedFoo) ==
+ static_cast<void (Overloaded::*)()>(&Overloaded::mixedFoo));
+
+ QVERIFY(qConstOverload<QByteArray>(&Overloaded::mixedFoo) ==
+ static_cast<void (Overloaded::*)(QByteArray) const>(&Overloaded::mixedFoo));
+#endif
+
+#endif
+}
+
+
QTEST_APPLESS_MAIN(tst_QGlobal)
#include "tst_qglobal.moc"