QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskMetaFunction.h
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#ifndef QSK_META_FUNCTION_H
7#define QSK_META_FUNCTION_H
8
9#include "QskGlobal.h"
10
11#include <qmetatype.h>
12#include <qobject.h>
13
14namespace QskMetaFunctionTraits
15{
16 using namespace QtPrivate;
17
18 template< typename T >
19 using IsMemberFunction = typename std::enable_if<
20 FunctionPointer< T >::IsPointerToMemberFunction, std::true_type >::type;
21
22 template< typename T >
23 using IsFunctorOrStaticFunction = typename std::enable_if<
24 !FunctionPointer< T >::IsPointerToMemberFunction, std::true_type >::type;
25
26 template< typename T >
27 using IsFunctor = typename std::enable_if<
28 !FunctionPointer< T >::IsPointerToMemberFunction
29 && FunctionPointer< T >::ArgumentCount == -1, std::true_type >::type;
30
31 template< typename T >
32 using IsStaticFunction = typename std::enable_if<
33 !FunctionPointer< T >::IsPointerToMemberFunction
34 && FunctionPointer< T >::ArgumentCount >= 0, std::true_type >::type;
35
36 template< typename T, IsMemberFunction< T >* = nullptr >
37 constexpr inline int argumentCount()
38 {
39 using Traits = FunctionPointer< T >;
40 return Traits::ArgumentCount;
41 }
42
43 template< typename T, IsStaticFunction< T >* = nullptr >
44 constexpr inline int argumentCount()
45 {
46 using Traits = FunctionPointer< T >;
47 return Traits::ArgumentCount;
48 }
49
50 template< typename T, IsFunctor< T >* = nullptr >
51 constexpr inline int argumentCount()
52 {
53 using Traits = FunctionPointer< decltype( &T::operator() ) >;
54 return Traits::ArgumentCount;
55 }
56
57 template< typename T, size_t i >
58 constexpr typename std::enable_if< i >= argumentCount< T >(), int >::type argumentType()
59 {
60 return QMetaType::UnknownType;
61 }
62
63 template< typename T, size_t i, IsMemberFunction< T >* = nullptr >
64 constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType()
65 {
66 return ConnectionTypes< typename FunctionPointer< T >::Arguments >::types()[ i ];
67 }
68
69 template< typename T, size_t i, IsStaticFunction< T >* = nullptr >
70 constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType()
71 {
72 return ConnectionTypes< typename FunctionPointer< T >::Arguments >::types()[ i ];
73 }
74
75 template< typename T, size_t i, IsFunctor< T >* = nullptr >
76 constexpr typename std::enable_if < i < argumentCount< T >(), int >::type argumentType()
77 {
78 using Traits = FunctionPointer< decltype( &T::operator() ) >;
79 return ConnectionTypes< typename Traits::Arguments >::types()[ i ];
80 }
81}
82
83class QSK_EXPORT QskMetaFunction
84{
85 Q_GADGET
86
87 public:
88 enum Type
89 {
90 Invalid = -1,
91
92 // a non static method of class
93 MemberFunction,
94
95 // a static function, or static method of a class
96 StaticFunction,
97
98 // a functor or lambda
99 Functor
100 };
101
102 Q_ENUM( Type )
103
105
108
109 template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* = nullptr >
110 QskMetaFunction( T );
111
112 template< typename T, QskMetaFunctionTraits::IsFunctor< T >* = nullptr >
113 QskMetaFunction( T );
114
115 template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* = nullptr >
116 QskMetaFunction( T );
117
119
120 QskMetaFunction& operator=( const QskMetaFunction& );
121 QskMetaFunction& operator=( QskMetaFunction&& );
122
123 bool operator==( const QskMetaFunction& ) const;
124 bool operator!=( const QskMetaFunction& ) const;
125
126 explicit operator bool() const;
127
128 int returnType() const;
129
130 size_t parameterCount() const;
131 const int* parameterTypes() const;
132
133 void invoke( QObject*, void* args[],
134 Qt::ConnectionType = Qt::AutoConnection );
135
136 Type functionType() const;
137 bool isNull() const;
138
139 class FunctionCall;
140 FunctionCall* functionCall() const;
141
142 protected:
144
145 private:
146 FunctionCall* m_functionCall;
147};
148
149inline bool QskMetaFunction::operator!=( const QskMetaFunction& other ) const
150{
151 return !( *this == other );
152}
153
154inline QskMetaFunction::operator bool() const
155{
156 return !isNull();
157}
158
159inline bool QskMetaFunction::isNull() const
160{
161 return m_functionCall == nullptr;
162}
163
164inline QskMetaFunction::FunctionCall* QskMetaFunction::functionCall() const
165{
166 return m_functionCall;
167}
168
169#include "QskMetaFunction.hpp"
170
171inline const int* QskMetaFunction::parameterTypes() const
172{
173 return m_functionCall ? m_functionCall->parameterTypes() : nullptr;
174}
175
176template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* >
177inline QskMetaFunction::QskMetaFunction( T function )
178{
179 using namespace QtPrivate;
180 using namespace QskMetaFunctionCall;
181
182 using Traits = FunctionPointer< T >;
183
184 constexpr int Argc = Traits::ArgumentCount;
185 using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
186
187 m_functionCall = new MemberFunctionCall< T, Args, void >( function );
188 m_functionCall->setParameterTypes(
189 ConnectionTypes< typename Traits::Arguments >::types() );
190}
191
192template< typename T, QskMetaFunctionTraits::IsFunctor< T >* >
193inline QskMetaFunction::QskMetaFunction( T functor )
194{
195 using namespace QtPrivate;
196 using namespace QskMetaFunctionCall;
197
198 using Traits = FunctionPointer< decltype( &T::operator() ) >;
199
200 constexpr int Argc = Traits::ArgumentCount;
201 using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
202
203 m_functionCall = new FunctorFunctionCall< T, Argc, Args, void >( functor );
204 m_functionCall->setParameterTypes(
205 ConnectionTypes< typename Traits::Arguments >::types() );
206}
207
208template< typename T, QskMetaFunctionTraits::IsStaticFunction< T >* >
209inline QskMetaFunction::QskMetaFunction( T function )
210{
211 using namespace QtPrivate;
212 using namespace QskMetaFunctionCall;
213
214 using Traits = FunctionPointer< T >;
215
216 constexpr int Argc = Traits::ArgumentCount;
217 using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
218
219 m_functionCall = new StaticFunctionCall< T, Args, void >( function );
220 m_functionCall->setParameterTypes(
221 ConnectionTypes< typename Traits::Arguments >::types() );
222}
223
224Q_DECLARE_METATYPE( QskMetaFunction )
225
226#endif