From 4cd45201f6a39d27413f7d086d4111def79fa8da Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 14 Mar 2018 14:45:39 +0100 Subject: [PATCH] more compile time checks, when using QskMetaFunction --- src/common/QskMetaFunction.cpp | 4 +- src/common/QskMetaFunction.h | 67 ++++++++++++++++++++----- src/common/QskMetaFunction.hpp | 4 +- src/controls/QskShortcutMap.cpp | 5 +- src/controls/QskShortcutMap.h | 86 ++++++++++++++++++++++----------- 5 files changed, 118 insertions(+), 48 deletions(-) diff --git a/src/common/QskMetaFunction.cpp b/src/common/QskMetaFunction.cpp index bf40bece..d4ea6862 100644 --- a/src/common/QskMetaFunction.cpp +++ b/src/common/QskMetaFunction.cpp @@ -139,8 +139,8 @@ bool QskMetaFunction::operator==( const QskMetaFunction& other ) const if ( m_functionCall && other.m_functionCall ) { - if ( m_functionCall->typeInfo() == Function && - other.m_functionCall->typeInfo() == Function ) + if ( m_functionCall->typeInfo() == StaticFunction && + other.m_functionCall->typeInfo() == StaticFunction ) { // only static functions can be compared return m_functionCall->compare( diff --git a/src/common/QskMetaFunction.h b/src/common/QskMetaFunction.h index 89815feb..f59d7873 100644 --- a/src/common/QskMetaFunction.h +++ b/src/common/QskMetaFunction.h @@ -8,26 +8,71 @@ #include "QskGlobal.h" #include +#include namespace QskMetaFunctionTraits { using namespace QtPrivate; template< typename T > - using IsMemberFunction = typename std::enable_if< FunctionPointer< T >::IsPointerToMemberFunction, - std::true_type >::type; + using IsMemberFunction = typename std::enable_if< + FunctionPointer< T >::IsPointerToMemberFunction, std::true_type >::type; template< typename T > - using IsFunctor = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction + using IsFunctor = typename std::enable_if< + !FunctionPointer< T >::IsPointerToMemberFunction && FunctionPointer< T >::ArgumentCount == -1, std::true_type >::type; template< typename T > - using IsFunction = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction + using IsStaticFunction = typename std::enable_if< + !FunctionPointer< T >::IsPointerToMemberFunction && FunctionPointer< T >::ArgumentCount >= 0, std::true_type >::type; - template< typename T > - using IsFunction0 = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction - && FunctionPointer< T >::ArgumentCount == 0, std::true_type >::type; + template< typename T, IsMemberFunction< T >* = nullptr > + constexpr inline int argumentCount() + { + using Traits = FunctionPointer< T >; + return Traits::ArgumentCount; + } + + template< typename T, IsStaticFunction< T >* = nullptr > + constexpr inline int argumentCount() + { + using Traits = FunctionPointer< T >; + return Traits::ArgumentCount; + } + + template< typename T, IsFunctor< T >* = nullptr > + constexpr inline int argumentCount() + { + using Traits = FunctionPointer< decltype( &T::operator() ) >; + return Traits::ArgumentCount; + } + + template< typename T, size_t i > + constexpr typename std::enable_if< i >= argumentCount< T >(), int >::type argumentType() + { + return QMetaType::UnknownType; + } + + template< typename T, size_t i, IsMemberFunction< T >* = nullptr > + constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType() + { + return ConnectionTypes< typename FunctionPointer< T >::Arguments >::types()[i]; + } + + template< typename T, size_t i, IsStaticFunction< T >* = nullptr > + constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType() + { + return ConnectionTypes< typename FunctionPointer< T >::Arguments >::types()[i]; + } + + template< typename T, size_t i, IsFunctor< T >* = nullptr > + constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType() + { + using Traits = FunctionPointer< decltype( &T::operator() ) >; + return ConnectionTypes< typename Traits::Arguments >::types()[i]; + } } class QSK_EXPORT QskMetaFunction @@ -40,10 +85,10 @@ public: Invalid = -1, // a non static method of class - Member, + MemberFunction, // a static function, or static method of a class - Function, + StaticFunction, // a functor or lambda Functor @@ -62,7 +107,7 @@ public: template< typename T, QskMetaFunctionTraits::IsFunctor< T >* = nullptr > QskMetaFunction( T ); - template< typename T, QskMetaFunctionTraits::IsFunction< T >* = nullptr > + template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* = nullptr > QskMetaFunction( T ); ~QskMetaFunction(); @@ -155,7 +200,7 @@ inline QskMetaFunction::QskMetaFunction( T functor ) ConnectionTypes< typename Traits::Arguments >::types() ); } -template< typename T, QskMetaFunctionTraits::IsFunction< T >* > +template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* > inline QskMetaFunction::QskMetaFunction( T function ) { using namespace QtPrivate; diff --git a/src/common/QskMetaFunction.hpp b/src/common/QskMetaFunction.hpp index 9b206ceb..4f8429f1 100644 --- a/src/common/QskMetaFunction.hpp +++ b/src/common/QskMetaFunction.hpp @@ -89,7 +89,7 @@ namespace QskMetaFunctionCall } case TypeInfo: { - *reinterpret_cast< int* >( args ) = QskMetaFunction::Function; + *reinterpret_cast< int* >( args ) = QskMetaFunction::StaticFunction; break; } } @@ -133,7 +133,7 @@ namespace QskMetaFunctionCall } case TypeInfo: { - *reinterpret_cast< int* >( args ) = QskMetaFunction::Member; + *reinterpret_cast< int* >( args ) = QskMetaFunction::MemberFunction; break; } } diff --git a/src/controls/QskShortcutMap.cpp b/src/controls/QskShortcutMap.cpp index 88b1b117..695a6bef 100644 --- a/src/controls/QskShortcutMap.cpp +++ b/src/controls/QskShortcutMap.cpp @@ -98,14 +98,11 @@ int QskShortcutHandler::insert( return 0; } -#if 1 - // should be a compile time check for functor based slots if ( invokable.parameterCount() > 0 ) { qDebug() << "QskShortcutMap: invalid slot parameter count"; return 0; } -#endif if ( receiver ) { @@ -271,7 +268,7 @@ int QskShortcutMap::addFunction( QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, const QObject* receiver, const QskMetaFunction& function ) { if ( ( receiver == nullptr ) - && ( function.functionType() == QskMetaFunction::Member ) ) + && ( function.functionType() == QskMetaFunction::MemberFunction ) ) { qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence; return 0; diff --git a/src/controls/QskShortcutMap.h b/src/controls/QskShortcutMap.h index fd4a611f..5395c69a 100644 --- a/src/controls/QskShortcutMap.h +++ b/src/controls/QskShortcutMap.h @@ -33,23 +33,29 @@ public: bool autoRepeat, const QObject* receiver, const char* method ); // functor based slots + template< typename T > static int addShortcut( const QKeySequence&, - bool autoRepeat, const QskMetaFunction& ); + bool autoRepeat, T function ); + template< typename T > static int addShortcut( const QKeySequence&, - bool autoRepeat, const QObject* context, const QskMetaFunction& ); + bool autoRepeat, const QObject* context, T function ); + template< typename T > static int addShortcut( QQuickItem*, const QKeySequence&, - bool autoRepeat, const QskMetaFunction& ); + bool autoRepeat, T function ); + template< typename T > static int addShortcut( QQuickItem*, const QKeySequence&, - bool autoRepeat, const QObject* context, const QskMetaFunction& ); + bool autoRepeat, const QObject* context, T function ); + template< typename T > static int addShortcut( QQuickWindow*, const QKeySequence&, - bool autoRepeat, const QskMetaFunction& ); + bool autoRepeat, T function ); + template< typename T > static int addShortcut( QQuickWindow*, const QKeySequence&, - bool autoRepeat, const QObject* context, const QskMetaFunction& ); + bool autoRepeat, const QObject* context, T function ); static bool contextMatcher( const QQuickItem*, Qt::ShortcutContext ); @@ -57,6 +63,11 @@ private: QskShortcutMap() = delete; ~QskShortcutMap() = delete; + template< typename T > + static int addFunctionT( + QQuickItem* item, const QKeySequence&, bool autoRepeat, + const QObject* receiver, T ); + static int addFunction( QQuickItem* item, const QKeySequence&, bool autoRepeat, const QObject* receiver, const QskMetaFunction& ); @@ -81,47 +92,64 @@ inline int QskShortcutMap::addShortcut( return addMethod( item, sequence, autoRepeat, receiver, method ); } +template< typename T > +inline int QskShortcutMap::addShortcut( + const QKeySequence& sequence, bool autoRepeat, T function ) +{ + return addFunctionT( nullptr, sequence, autoRepeat, nullptr, function ); +} + +template< typename T > inline int QskShortcutMap::addShortcut( const QKeySequence& sequence, bool autoRepeat, - const QskMetaFunction& function ) + const QObject* context, T function ) { - return addFunction( nullptr, sequence, autoRepeat, nullptr, function ); + return addFunctionT( nullptr, sequence, autoRepeat, context, function ); } +template< typename T > inline int QskShortcutMap::addShortcut( - const QKeySequence& sequence, bool autoRepeat, - const QObject* context, const QskMetaFunction& function ) + QQuickItem* item, const QKeySequence& sequence, + bool autoRepeat, T function ) { - return addFunction( nullptr, sequence, autoRepeat, context, function ); + return addFunctionT( item, sequence, autoRepeat, nullptr, function ); } +template< typename T > inline int QskShortcutMap::addShortcut( QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const QskMetaFunction& function ) + const QObject* context, T function ) { - return addFunction( item, sequence, autoRepeat, nullptr, function ); + return addFunctionT( item, sequence, autoRepeat, + context, QskMetaFunction( function ) ); } +template< typename T > inline int QskShortcutMap::addShortcut( + QQuickWindow* window, const QKeySequence& sequence, + bool autoRepeat, T function ) +{ + auto item = window ? window->contentItem() : nullptr; + return addFunctionT( item, sequence, autoRepeat, nullptr, function ); +} + +template< typename T > +inline int QskShortcutMap::addShortcut( + QQuickWindow* window, const QKeySequence& sequence, + bool autoRepeat, const QObject* context, T function ) +{ + auto item = window ? window->contentItem() : nullptr; + return addFunctionT( item, sequence, autoRepeat, context, function ); +} + +template< typename T > +inline int QskShortcutMap::addFunctionT( QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, - const QObject* context, const QskMetaFunction& function ) + const QObject* context, T function ) { - return addFunction( item, sequence, autoRepeat, context, function ); -} + static_assert( QskMetaFunctionTraits::argumentCount< T >() == 0, + "QskShortcutMap::addShortcut: #number of arguments need to be 0." ); -inline int QskShortcutMap::addShortcut( - QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, - const QskMetaFunction& function ) -{ - auto item = window ? window->contentItem() : nullptr; - return addFunction( item, sequence, autoRepeat, nullptr, function ); -} - -inline int QskShortcutMap::addShortcut( - QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, - const QObject* context, const QskMetaFunction& function ) -{ - auto item = window ? window->contentItem() : nullptr; return addFunction( item, sequence, autoRepeat, context, function ); }