more compile time checks, when using QskMetaFunction

This commit is contained in:
Uwe Rathmann 2018-03-14 14:45:39 +01:00
parent 0930085a64
commit 4cd45201f6
5 changed files with 118 additions and 48 deletions

View File

@ -139,8 +139,8 @@ bool QskMetaFunction::operator==( const QskMetaFunction& other ) const
if ( m_functionCall && other.m_functionCall ) if ( m_functionCall && other.m_functionCall )
{ {
if ( m_functionCall->typeInfo() == Function && if ( m_functionCall->typeInfo() == StaticFunction &&
other.m_functionCall->typeInfo() == Function ) other.m_functionCall->typeInfo() == StaticFunction )
{ {
// only static functions can be compared // only static functions can be compared
return m_functionCall->compare( return m_functionCall->compare(

View File

@ -8,26 +8,71 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include <QMetaType> #include <QMetaType>
#include <QObject>
namespace QskMetaFunctionTraits namespace QskMetaFunctionTraits
{ {
using namespace QtPrivate; using namespace QtPrivate;
template< typename T > template< typename T >
using IsMemberFunction = typename std::enable_if< FunctionPointer< T >::IsPointerToMemberFunction, using IsMemberFunction = typename std::enable_if<
std::true_type >::type; FunctionPointer< T >::IsPointerToMemberFunction, std::true_type >::type;
template< typename T > 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; && FunctionPointer< T >::ArgumentCount == -1, std::true_type >::type;
template< typename T > 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; && FunctionPointer< T >::ArgumentCount >= 0, std::true_type >::type;
template< typename T > template< typename T, IsMemberFunction< T >* = nullptr >
using IsFunction0 = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction constexpr inline int argumentCount()
&& FunctionPointer< T >::ArgumentCount == 0, std::true_type >::type; {
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 class QSK_EXPORT QskMetaFunction
@ -40,10 +85,10 @@ public:
Invalid = -1, Invalid = -1,
// a non static method of class // a non static method of class
Member, MemberFunction,
// a static function, or static method of a class // a static function, or static method of a class
Function, StaticFunction,
// a functor or lambda // a functor or lambda
Functor Functor
@ -62,7 +107,7 @@ public:
template< typename T, QskMetaFunctionTraits::IsFunctor< T >* = nullptr > template< typename T, QskMetaFunctionTraits::IsFunctor< T >* = nullptr >
QskMetaFunction( T ); QskMetaFunction( T );
template< typename T, QskMetaFunctionTraits::IsFunction< T >* = nullptr > template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* = nullptr >
QskMetaFunction( T ); QskMetaFunction( T );
~QskMetaFunction(); ~QskMetaFunction();
@ -155,7 +200,7 @@ inline QskMetaFunction::QskMetaFunction( T functor )
ConnectionTypes< typename Traits::Arguments >::types() ); ConnectionTypes< typename Traits::Arguments >::types() );
} }
template< typename T, QskMetaFunctionTraits::IsFunction< T >* > template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* >
inline QskMetaFunction::QskMetaFunction( T function ) inline QskMetaFunction::QskMetaFunction( T function )
{ {
using namespace QtPrivate; using namespace QtPrivate;

View File

@ -89,7 +89,7 @@ namespace QskMetaFunctionCall
} }
case TypeInfo: case TypeInfo:
{ {
*reinterpret_cast< int* >( args ) = QskMetaFunction::Function; *reinterpret_cast< int* >( args ) = QskMetaFunction::StaticFunction;
break; break;
} }
} }
@ -133,7 +133,7 @@ namespace QskMetaFunctionCall
} }
case TypeInfo: case TypeInfo:
{ {
*reinterpret_cast< int* >( args ) = QskMetaFunction::Member; *reinterpret_cast< int* >( args ) = QskMetaFunction::MemberFunction;
break; break;
} }
} }

View File

@ -98,14 +98,11 @@ int QskShortcutHandler::insert(
return 0; return 0;
} }
#if 1
// should be a compile time check for functor based slots
if ( invokable.parameterCount() > 0 ) if ( invokable.parameterCount() > 0 )
{ {
qDebug() << "QskShortcutMap: invalid slot parameter count"; qDebug() << "QskShortcutMap: invalid slot parameter count";
return 0; return 0;
} }
#endif
if ( receiver ) if ( receiver )
{ {
@ -271,7 +268,7 @@ int QskShortcutMap::addFunction( QQuickItem* item, const QKeySequence& sequence,
bool autoRepeat, const QObject* receiver, const QskMetaFunction& function ) bool autoRepeat, const QObject* receiver, const QskMetaFunction& function )
{ {
if ( ( receiver == nullptr ) if ( ( receiver == nullptr )
&& ( function.functionType() == QskMetaFunction::Member ) ) && ( function.functionType() == QskMetaFunction::MemberFunction ) )
{ {
qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence; qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence;
return 0; return 0;

View File

@ -33,23 +33,29 @@ public:
bool autoRepeat, const QObject* receiver, const char* method ); bool autoRepeat, const QObject* receiver, const char* method );
// functor based slots // functor based slots
template< typename T >
static int addShortcut( const QKeySequence&, static int addShortcut( const QKeySequence&,
bool autoRepeat, const QskMetaFunction& ); bool autoRepeat, T function );
template< typename T >
static int addShortcut( const QKeySequence&, 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&, static int addShortcut( QQuickItem*, const QKeySequence&,
bool autoRepeat, const QskMetaFunction& ); bool autoRepeat, T function );
template< typename T >
static int addShortcut( QQuickItem*, const QKeySequence&, 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&, static int addShortcut( QQuickWindow*, const QKeySequence&,
bool autoRepeat, const QskMetaFunction& ); bool autoRepeat, T function );
template< typename T >
static int addShortcut( QQuickWindow*, const QKeySequence&, 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 ); static bool contextMatcher( const QQuickItem*, Qt::ShortcutContext );
@ -57,6 +63,11 @@ private:
QskShortcutMap() = delete; QskShortcutMap() = delete;
~QskShortcutMap() = delete; ~QskShortcutMap() = delete;
template< typename T >
static int addFunctionT(
QQuickItem* item, const QKeySequence&, bool autoRepeat,
const QObject* receiver, T );
static int addFunction( static int addFunction(
QQuickItem* item, const QKeySequence&, bool autoRepeat, QQuickItem* item, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const QskMetaFunction& ); const QObject* receiver, const QskMetaFunction& );
@ -81,47 +92,64 @@ inline int QskShortcutMap::addShortcut(
return addMethod( item, sequence, autoRepeat, receiver, method ); 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( inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, 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( inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, QQuickItem* item, const QKeySequence& sequence,
const QObject* context, const QskMetaFunction& function ) 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( inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, 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( 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, 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 ); return addFunction( item, sequence, autoRepeat, context, function );
} }