diff options
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp | 23 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 43 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 60 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 6 | ||||
-rw-r--r-- | tests/auto/corelib/global/qglobal/tst_qglobal.cpp | 122 |
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" |