1 | /**************************************************************************** |
2 | * Copyright (C) 2016-2018 Woboq GmbH |
3 | * Olivier Goffart <ogoffart at woboq.com> |
4 | * https://woboq.com/ |
5 | * |
6 | * This file is part of Verdigris: a way to use Qt without moc. |
7 | * https://github.com/woboq/verdigris |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify |
10 | * it under the terms of the GNU Lesser General Public License as |
11 | * published by the Free Software Foundation, either version 3 of the |
12 | * License, or (at your option) any later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with this program. |
21 | * If not, see <http://www.gnu.org/licenses/>. |
22 | */ |
23 | #pragma once |
24 | |
25 | #ifndef Q_MOC_RUN // don't define anything when moc is run |
26 | |
27 | #include <QtCore/qobjectdefs.h> |
28 | #include <QtCore/qmetatype.h> |
29 | #include <utility> |
30 | |
31 | #define W_VERSION 0x010200 |
32 | |
33 | namespace w_internal { |
34 | using std::index_sequence; // From C++14, make sure to enable the C++14 option in your compiler |
35 | |
36 | #ifdef W_USE_CUSTOM_MAKE_INDEX_SEQUENCE |
37 | // The default std::make_index_sequence from libstdc++ is recursing O(N) times which is reaching |
38 | // recursion limits level for big strings. This implementation has only O(log N) recursion |
39 | template<size_t... I1, size_t... I2> |
40 | index_sequence<I1... , (I2 +(sizeof...(I1)))...> |
41 | make_index_sequence_helper_merge(index_sequence<I1...>, index_sequence<I2...>); |
42 | |
43 | template<std::size_t N> struct make_index_sequence_helper { |
44 | using part1 = typename make_index_sequence_helper<(N+1)/2>::result; |
45 | using part2 = typename make_index_sequence_helper<N/2>::result; |
46 | using result = decltype(make_index_sequence_helper_merge(part1(), part2())); |
47 | }; |
48 | template<> struct make_index_sequence_helper<1> { using result = index_sequence<0>; }; |
49 | template<> struct make_index_sequence_helper<0> { using result = index_sequence<>; }; |
50 | template<std::size_t N> using make_index_sequence = typename make_index_sequence_helper<N>::result; |
51 | #else |
52 | using std::make_index_sequence; |
53 | #endif |
54 | |
55 | /// integral_constant with an inheritance based fallback |
56 | struct IndexBase {}; |
57 | template <size_t> struct Index : IndexBase {}; |
58 | template <size_t I> constexpr auto index = Index<I>{}; |
59 | |
60 | template<typename... Args> constexpr void ordered(Args...) {} |
61 | template<class T> constexpr void ordered2(std::initializer_list<T>) {} |
62 | |
63 | /// Compute the sum of many integers |
64 | template<typename... Args> |
65 | constexpr int sums(Args... args) { |
66 | #if __cplusplus > 201700L |
67 | return static_cast<int>((args + ... + 0)); |
68 | #else |
69 | auto r = int{}; |
70 | ordered2<int>({(r += args)...}); |
71 | return r; |
72 | #endif |
73 | } |
74 | // This indirection is required to work around a MSVC bug. (See https://github.com/woboq/verdigris/issues/6 ) |
75 | template <int ...args> |
76 | constexpr int summed = sums(args...); |
77 | |
78 | /// constexpr friendly string_view |
79 | struct StringView { |
80 | const char* b{}; |
81 | const char* e{}; |
82 | |
83 | constexpr auto size() const -> size_t { return static_cast<size_t>(e-b); } |
84 | constexpr auto begin() const { return b; } |
85 | constexpr auto end() const { return e; } |
86 | }; |
87 | // adding this constructor requires more constructors which generates overhead |
88 | template<size_t N> |
89 | constexpr auto viewLiteral(const char (&d)[N]) -> StringView { |
90 | return {&d[0], &d[N]}; |
91 | } |
92 | |
93 | /// raw arrays cannot be returned from functions so we wrap it |
94 | template<size_t N = 0> |
95 | struct StringViewArray { |
96 | StringView data[(N > 0 ? N : 1)]{}; |
97 | |
98 | constexpr auto operator[] (size_t i) const { return data[i]; } |
99 | }; |
100 | |
101 | template<size_t... Ns> |
102 | constexpr size_t countValidSizes() { |
103 | auto c = size_t{}; |
104 | #if __cplusplus > 201700L |
105 | (void)(true && ... && (Ns > 1 ? ++c : false)); |
106 | #else |
107 | auto b = true; |
108 | ordered2<size_t>({((Ns > 1 && b ? (c += 1) : ((void)(b=false), c)))...}); |
109 | #endif |
110 | return c; |
111 | } |
112 | template<size_t R, size_t... Ns, size_t... Ts, size_t... Is, class... Args> |
113 | constexpr auto viewValidTailsImpl(index_sequence<Is...>, index_sequence<Ts...>, const Args& ... ns) { |
114 | auto r = StringViewArray<R>{}; |
115 | #if __cplusplus > 201700L |
116 | auto p = r.data; |
117 | ((Is < R ? (*p++ = StringView{&ns[Ns - Ts], &ns[Ns]}) : *p), ...); |
118 | #else |
119 | auto i = 0; |
120 | ordered2<int>({(Is < R ? (r.data[i++] = StringView{&ns[Ns - Ts], &ns[Ns]}, 0) : 0)...}); |
121 | #endif |
122 | return r; |
123 | } |
124 | template<size_t... Ts, size_t... Ns> |
125 | constexpr auto viewValidTails(const char (& ...ns)[Ns]) { |
126 | constexpr auto r = countValidSizes<Ts...>(); |
127 | constexpr auto is = make_index_sequence<sizeof... (Ns)>{}; |
128 | return viewValidTailsImpl<r, Ns...>(is, index_sequence<Ts...>{}, ns...); |
129 | } |
130 | |
131 | template<size_t R, size_t... Ns, size_t... Is, class... Args> |
132 | constexpr auto viewValidLiteralsImpl(index_sequence<Is...>, const Args& ... ns) { |
133 | auto r = StringViewArray<R>{}; |
134 | #if __cplusplus > 201700L |
135 | auto p = r.data; |
136 | ((Is < R ? (*p++ = viewLiteral(ns)) : *p), ...); |
137 | #else |
138 | ordered((Is < R ? (r.data[Is] = viewLiteral(ns), 0) : 0)...); |
139 | #endif |
140 | return r; |
141 | } |
142 | template<size_t... Ns> |
143 | constexpr auto viewValidLiterals(const char (& ...ns)[Ns]) { |
144 | constexpr auto r = countValidSizes<Ns...>(); |
145 | constexpr auto is = make_index_sequence<sizeof... (Ns)>{}; |
146 | return viewValidLiteralsImpl<r, Ns...>(is, ns...); |
147 | } |
148 | |
149 | //----------- |
150 | |
151 | // From qmetaobject_p.h |
152 | enum class PropertyFlags { |
153 | Invalid = 0x00000000, |
154 | Readable = 0x00000001, |
155 | Writable = 0x00000002, |
156 | Resettable = 0x00000004, |
157 | EnumOrFlag = 0x00000008, |
158 | StdCppSet = 0x00000100, |
159 | // Override = 0x00000200, |
160 | Constant = 0x00000400, |
161 | Final = 0x00000800, |
162 | Designable = 0x00001000, |
163 | ResolveDesignable = 0x00002000, |
164 | Scriptable = 0x00004000, |
165 | ResolveScriptable = 0x00008000, |
166 | Stored = 0x00010000, |
167 | ResolveStored = 0x00020000, |
168 | Editable = 0x00040000, |
169 | ResolveEditable = 0x00080000, |
170 | User = 0x00100000, |
171 | ResolveUser = 0x00200000, |
172 | Notify = 0x00400000, |
173 | Revisioned = 0x00800000 |
174 | }; |
175 | constexpr uint operator|(uint a, PropertyFlags b) { return a | uint(b); } |
176 | |
177 | template <int N> struct W_MethodFlags { static constexpr int value = N; }; |
178 | constexpr W_MethodFlags<0> W_EmptyFlag{}; |
179 | |
180 | } // namespace w_internal |
181 | |
182 | /// Objects that are used as flags in the W_SLOT macro |
183 | |
184 | // Mirror of QMetaMethod::Access |
185 | namespace W_Access { |
186 | // From qmetaobject_p.h MethodFlags |
187 | // AccessPrivate = 0x00, |
188 | // AccessProtected = 0x01, |
189 | // AccessPublic = 0x02, |
190 | // AccessMask = 0x03, //mask |
191 | constexpr w_internal::W_MethodFlags<0x1000> Private{}; // Note: Private has a higher number to differentiate it from the default |
192 | constexpr w_internal::W_MethodFlags<0x01> Protected{}; |
193 | constexpr w_internal::W_MethodFlags<0x02> Public{}; |
194 | } |
195 | |
196 | // Mirror of QMetaMethod::MethodType |
197 | namespace W_MethodType { |
198 | // From qmetaobject_p.h MethodFlags |
199 | // MethodMethod = 0x00, |
200 | // MethodSignal = 0x04, |
201 | // MethodSlot = 0x08, |
202 | // MethodConstructor = 0x0c, |
203 | // MethodTypeMask = 0x0c, |
204 | constexpr w_internal::W_MethodFlags<0x00> Method{}; |
205 | constexpr w_internal::W_MethodFlags<0x04> Signal{}; |
206 | constexpr w_internal::W_MethodFlags<0x08> Slot{}; |
207 | constexpr w_internal::W_MethodFlags<0x0c> Constructor{}; |
208 | } |
209 | |
210 | // From qmetaobject_p.h MethodFlags |
211 | // MethodCompatibility = 0x10, |
212 | // MethodCloned = 0x20, |
213 | // MethodScriptable = 0x40, |
214 | // MethodRevisioned = 0x80 |
215 | constexpr w_internal::W_MethodFlags<0x10> W_Compat{}; |
216 | constexpr w_internal::W_MethodFlags<0x40> W_Scriptable{}; |
217 | constexpr struct {} W_Notify{}; |
218 | constexpr struct {} W_Reset{}; |
219 | constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Constant)> W_Constant{}; |
220 | constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Final)> W_Final{}; |
221 | |
222 | namespace w_internal { |
223 | |
224 | /// Holds information about a method |
225 | template<typename F, int Flags, typename IC, typename ParamTypes, typename ParamNames = StringViewArray<>> |
226 | struct MetaMethodInfo { |
227 | F func; |
228 | StringView name; |
229 | ParamTypes paramTypes; |
230 | ParamNames paramNames; |
231 | static constexpr int argCount = QtPrivate::FunctionPointer<F>::ArgumentCount; |
232 | static constexpr auto argSequence = make_index_sequence<argCount>{}; |
233 | static constexpr int flags = Flags; |
234 | using IntegralConstant = IC; |
235 | }; |
236 | |
237 | // Called from the W_SLOT macro |
238 | template<typename F, typename ParamTypes, int... Flags, typename IntegralConstant> |
239 | constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Slot.value, IntegralConstant, ParamTypes> |
240 | makeMetaSlotInfo(F f, StringView name, IntegralConstant, const ParamTypes ¶mTypes, W_MethodFlags<Flags>...) |
241 | { return { f, name, paramTypes, {} }; } |
242 | |
243 | // Called from the W_METHOD macro |
244 | template<typename F, typename ParamTypes, int... Flags, typename IntegralConstant> |
245 | constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Method.value, IntegralConstant, ParamTypes> |
246 | makeMetaMethodInfo(F f, StringView name, IntegralConstant, const ParamTypes ¶mTypes, W_MethodFlags<Flags>...) |
247 | { return { f, name, paramTypes, {} }; } |
248 | |
249 | // Called from the W_SIGNAL macro |
250 | template<typename F, typename ParamTypes, typename ParamNames, int... Flags, typename IntegralConstant> |
251 | constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Signal.value, IntegralConstant, |
252 | ParamTypes, ParamNames> |
253 | makeMetaSignalInfo(F f, StringView name, IntegralConstant, const ParamTypes ¶mTypes, |
254 | const ParamNames ¶mNames, W_MethodFlags<Flags>...) |
255 | { return { f, name, paramTypes, paramNames }; } |
256 | |
257 | /// Holds information about a constructor |
258 | template<typename... Args> |
259 | struct MetaConstructorInfo { |
260 | static constexpr std::size_t argCount = sizeof...(Args); |
261 | static constexpr auto argSequence = make_index_sequence<argCount>{}; |
262 | static constexpr int flags = W_MethodType::Constructor.value | W_Access::Public.value; |
263 | using IntegralConstant = void*; // Used to detect the access specifier, but it is always public, so no need for this |
264 | StringView name; |
265 | }; |
266 | // called from the W_CONSTRUCTOR macro |
267 | template<typename... Args> |
268 | constexpr MetaConstructorInfo<Args...> makeMetaConstructorInfo(StringView name) |
269 | { return { name }; } |
270 | |
271 | struct Empty{ |
272 | constexpr operator bool() const { return false; } |
273 | }; |
274 | |
275 | /// Holds information about a property |
276 | template<typename Type, typename Getter = Empty, typename Setter = Empty, |
277 | typename Member = Empty, typename Notify = Empty, typename Reset = Empty, int Flags = 0> |
278 | struct MetaPropertyInfo { |
279 | using PropertyType = Type; |
280 | StringView name; |
281 | StringView typeStr; |
282 | Getter getter; |
283 | Setter setter; |
284 | Member member; |
285 | Notify notify; |
286 | Reset reset; |
287 | static constexpr uint flags = Flags; |
288 | |
289 | template <typename S> constexpr auto setGetter(const S&s) const { |
290 | return MetaPropertyInfo<Type, S, Setter, Member, Notify, Reset, |
291 | Flags | PropertyFlags::Readable> |
292 | {name, typeStr, s, setter, member, notify, reset}; |
293 | } |
294 | template <typename S> constexpr auto setSetter(const S&s) const { |
295 | return MetaPropertyInfo<Type, Getter, S, Member, Notify, Reset, |
296 | Flags | PropertyFlags::Writable> |
297 | {name, typeStr, getter, s, member, notify, reset}; |
298 | } |
299 | template <typename S> constexpr auto setMember(const S&s) const { |
300 | return MetaPropertyInfo<Type, Getter, Setter, S, Notify, Reset, |
301 | Flags | PropertyFlags::Writable | PropertyFlags::Readable> |
302 | {name, typeStr, getter, setter, s, notify, reset}; |
303 | } |
304 | template <typename S> constexpr auto setNotify(const S&s) const { |
305 | return MetaPropertyInfo<Type, Getter, Setter, Member, S, Reset, |
306 | Flags | PropertyFlags::Notify> |
307 | { name, typeStr, getter, setter, member, s, reset}; |
308 | } |
309 | template <typename S> constexpr auto setReset(const S&s) const { |
310 | return MetaPropertyInfo<Type, Getter, Setter, Member, Notify, S, |
311 | Flags | PropertyFlags::Resettable> |
312 | { name, typeStr, getter, setter, member, notify, s}; |
313 | } |
314 | template <int Flag> constexpr auto addFlag() const { |
315 | return MetaPropertyInfo<Type, Getter, Setter, Member, Notify, Reset, |
316 | Flags | Flag> |
317 | { name, typeStr, getter, setter, member, notify, reset}; |
318 | } |
319 | }; |
320 | |
321 | /// Parse a property and fill a MetaPropertyInfo (called from W_PROPERTY macro) |
322 | // base case |
323 | template <typename PropInfo> constexpr auto parseProperty(const PropInfo &p) { return p; } |
324 | // setter |
325 | template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail> |
326 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg), Tail... t) |
327 | { return parseProperty(p.setSetter(s) , t...); } |
328 | #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 |
329 | template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail> |
330 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg) noexcept, Tail... t) |
331 | { return parseProperty(p.setSetter(s) , t...); } |
332 | #endif |
333 | // getter |
334 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
335 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(), Tail... t) |
336 | { return parseProperty(p.setGetter(s), t...); } |
337 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
338 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const, Tail... t) |
339 | { return parseProperty(p.setGetter(s), t...); } |
340 | #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 |
341 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
342 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() noexcept, Tail... t) |
343 | { return parseProperty(p.setGetter(s), t...); } |
344 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
345 | constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const noexcept, Tail... t) |
346 | { return parseProperty(p.setGetter(s), t...); } |
347 | #endif |
348 | // member |
349 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
350 | constexpr auto parseProperty(const PropInfo &p, Ret Obj::*s, Tail... t) |
351 | { return parseProperty(p.setMember(s) ,t...); } |
352 | // notify |
353 | template <typename PropInfo, typename F, typename... Tail> |
354 | constexpr auto parseProperty(const PropInfo &p, decltype(W_Notify), F f, Tail... t) |
355 | { return parseProperty(p.setNotify(f) ,t...); } |
356 | // reset |
357 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
358 | constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)(), Tail... t) |
359 | { return parseProperty(p.setReset(s) ,t...); } |
360 | #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 |
361 | template <typename PropInfo, typename Obj, typename Ret, typename... Tail> |
362 | constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)() noexcept, Tail... t) |
363 | { return parseProperty(p.setReset(s) ,t...); } |
364 | #endif |
365 | // other flags flags |
366 | template <typename PropInfo, int Flag, typename... Tail> |
367 | constexpr auto parseProperty(const PropInfo &p, std::integral_constant<int, Flag>, Tail... t) |
368 | { return parseProperty(p.template addFlag<Flag>() ,t...); } |
369 | |
370 | template<typename T, typename ... Args> |
371 | constexpr auto makeMetaPropertyInfo(StringView name, StringView type, Args... args) { |
372 | auto meta = MetaPropertyInfo<T>{ name, type, {}, {}, {}, {}, {} }; |
373 | return parseProperty(meta, args...); |
374 | } |
375 | |
376 | template <typename T, typename = void> struct EnumIsScoped { |
377 | enum { Value = std::is_convertible<T, int>::value ? 0 : 2 }; |
378 | }; |
379 | template <typename T> struct EnumIsScoped<QFlags<T>, void> : EnumIsScoped<typename QFlags<T>::enum_type> {}; |
380 | |
381 | template<typename T> struct QEnumOrQFlags { using Type = T; }; |
382 | template<typename T> struct QEnumOrQFlags<QFlags<T>> { using Type = T; }; |
383 | |
384 | /// Holds information about an enum |
385 | template<bool HasAlias, typename Values_, typename Names, int Flags> |
386 | struct MetaEnumInfo { |
387 | StringView name; |
388 | StringView alias; |
389 | Names names; |
390 | using Values = Values_; |
391 | static constexpr uint flags = Flags; |
392 | static constexpr auto count = Values::size(); |
393 | static constexpr auto sequence = make_index_sequence<count>{}; |
394 | static constexpr auto hasAlias = HasAlias; |
395 | }; |
396 | template<typename Enum, Enum... Value> struct enum_sequence {}; |
397 | // called from W_ENUM and W_FLAG |
398 | template<typename Enum, int Flag, Enum... Values, typename Names> |
399 | constexpr auto makeMetaEnumInfo(StringView name, int, enum_sequence<Enum, Values...>, Names names) |
400 | -> MetaEnumInfo<false, index_sequence<size_t(Values)...>, Names, Flag | EnumIsScoped<Enum>::Value> { |
401 | return { name, viewLiteral("" ), names }; |
402 | } |
403 | template<typename Enum, int Flag, Enum... Values, typename Names> |
404 | constexpr auto makeMetaEnumInfo(StringView name, StringView alias, enum_sequence<Enum, Values...>, Names names) |
405 | -> MetaEnumInfo<true, index_sequence<size_t(Values)...>, Names, Flag | EnumIsScoped<Enum>::Value> { |
406 | return { name, alias, names }; |
407 | } |
408 | |
409 | // Helper function to remove the scope in a scoped enum name. (so "Foo::Bar" -> Bar) |
410 | template<int N> constexpr int removedScopeSize(const char (&name)[N]) { |
411 | // Find the position of the last colon (or 0 if it is not there) |
412 | int p = N - 1; |
413 | while (p > 0 && name[p] != ':') |
414 | p--; |
415 | if (name[p] == ':') |
416 | p++; |
417 | return N - p; |
418 | } |
419 | |
420 | /// Helper for the implementation of a signal. |
421 | /// Called from the signal implementation within the W_SIGNAL macro. |
422 | /// |
423 | /// 'Func' is the type of the signal. 'Idx' is the signal index (relative). |
424 | /// It is implemented as a functor so the operator() has exactly the same amount of argument of the |
425 | /// signal so the __VA_ARGS__ works also if there is no arguments (no leading commas) |
426 | /// |
427 | /// There is specialization for const and non-const, and for void and non-void signals. |
428 | /// |
429 | /// the last argument of the operator() is an int, to workaround the ",0" required in the W_SIGNAL |
430 | /// macro to make sure there is at least one argument for the ... |
431 | template<typename Func, int Idx> struct SignalImplementation {}; |
432 | template<typename Obj, typename Ret, typename... Args, int Idx> |
433 | struct SignalImplementation<Ret (Obj::*)(Args...), Idx>{ |
434 | Obj *this_; |
435 | Ret operator()(Args... args, int) const { |
436 | Ret r{}; |
437 | const void * a[]= { std::addressof(r), std::addressof(args)... }; |
438 | QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast<void **>(a)); |
439 | return r; |
440 | } |
441 | }; |
442 | template<typename Obj, typename... Args, int Idx> |
443 | struct SignalImplementation<void (Obj::*)(Args...), Idx>{ |
444 | Obj *this_; |
445 | void operator()(Args... args, int) { |
446 | const void * a[]= { nullptr, std::addressof(args)... }; |
447 | QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast<void **>(a)); |
448 | } |
449 | }; |
450 | template<typename Obj, typename Ret, typename... Args, int Idx> |
451 | struct SignalImplementation<Ret (Obj::*)(Args...) const, Idx>{ |
452 | const Obj *this_; |
453 | Ret operator()(Args... args, int) const { |
454 | Ret r{}; |
455 | const void * a[]= { std::addressof(r), std::addressof(args)... }; |
456 | QMetaObject::activate(const_cast<Obj*>(this_), &Obj::staticMetaObject, Idx, const_cast<void **>(a)); |
457 | return r; |
458 | } |
459 | }; |
460 | template<typename Obj, typename... Args, int Idx> |
461 | struct SignalImplementation<void (Obj::*)(Args...) const, Idx>{ |
462 | const Obj *this_; |
463 | void operator()(Args... args, int) { |
464 | const void * a[]= { nullptr, std::addressof(args)... }; |
465 | QMetaObject::activate(const_cast<Obj*>(this_), &Obj::staticMetaObject, Idx, const_cast<void **>(a)); |
466 | } |
467 | }; |
468 | |
469 | /// Used in the W_OBJECT macro to compute the base type. |
470 | /// Used like this: |
471 | /// using W_BaseType = std::remove_reference_t<decltype(getParentObjectHelper(&W_ThisType::qt_metacast))>; |
472 | /// Since qt_metacast for W_ThisType will be declared later, the pointer to member function will be |
473 | /// pointing to the qt_metacast of the base class, so T will be deduced to the base class type. |
474 | /// |
475 | /// Returns a reference so this work if T is an abstract class. |
476 | template<typename T> T &getParentObjectHelper(void* (T::*)(const char*)); |
477 | |
478 | // helper class that can access the private member of any class with W_OBJECT |
479 | struct FriendHelper; |
480 | |
481 | inline namespace w_ShouldBeInQt { |
482 | // qOverload is already in Qt 5.7, but we need it with older version. |
483 | // Note that as of Qt 5.11, it is still not enabled with MSVC as Qt relies on feature macro. |
484 | template <typename... Args> |
485 | struct QNonConstOverload |
486 | { |
487 | template <typename R, typename T> |
488 | constexpr auto operator()(R (T::*ptr)(Args...)) const |
489 | { return ptr; } |
490 | }; |
491 | template <typename... Args> |
492 | struct QConstOverload |
493 | { |
494 | template <typename R, typename T> |
495 | constexpr auto operator()(R (T::*ptr)(Args...) const) const |
496 | { return ptr; } |
497 | }; |
498 | template <typename... Args> |
499 | struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...> |
500 | { |
501 | using QConstOverload<Args...>::operator(); |
502 | using QNonConstOverload<Args...>::operator(); |
503 | |
504 | template <typename R> |
505 | constexpr auto operator()(R (*ptr)(Args...)) const |
506 | { return ptr; } |
507 | }; |
508 | template <typename... Args> constexpr QOverload<Args...> qOverload = {}; |
509 | |
510 | #ifndef QT_ANNOTATE_CLASS // Was added in Qt 5.6.1 |
511 | #define QT_ANNOTATE_CLASS(...) |
512 | #endif |
513 | } // namespace w_ShouldBeInQt |
514 | |
515 | } // namespace w_internal |
516 | |
517 | #if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) |
518 | // Workaround for MSVC: expension rules are different so we need some extra macro. |
519 | #define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__ |
520 | #define W_MACRO_MSVC_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) |
521 | #define W_MACRO_MSVC_EMPTY /##* *##/ |
522 | #else |
523 | #define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__ |
524 | #define W_MACRO_MSVC_DELAY(X,...) X(__VA_ARGS__) |
525 | #define W_MACRO_MSVC_EMPTY |
526 | #endif |
527 | |
528 | // Private macro helpers for macro programming |
529 | #define W_MACRO_EMPTY |
530 | #define W_MACRO_EVAL(...) __VA_ARGS__ |
531 | #define W_MACRO_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) |
532 | #define W_MACRO_DELAY2(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) |
533 | #define W_MACRO_TAIL(A, ...) __VA_ARGS__ |
534 | #define W_MACRO_FIRST(...) W_MACRO_MSVC_EXPAND(W_MACRO_FIRST2(__VA_ARGS__,)) |
535 | #define W_MACRO_FIRST2(A, ...) A |
536 | #define W_MACRO_STRIGNIFY(...) W_MACRO_STRIGNIFY2(__VA_ARGS__) |
537 | #define W_MACRO_STRIGNIFY2(...) #__VA_ARGS__ |
538 | #define W_MACRO_CONCAT(A, B) W_MACRO_CONCAT2(A,B) |
539 | #define W_MACRO_CONCAT2(A, B) A##_##B |
540 | |
541 | // strignify and make a StaticStringList out of an array of arguments |
542 | #define W_PARAM_TOSTRING(...) W_MACRO_MSVC_EMPTY W_MACRO_MSVC_DELAY(W_PARAM_TOSTRING2,__VA_ARGS__ ,,,,,,,,,,,,,,,,) |
543 | #define W_PARAM_TOSTRING2(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,...) \ |
544 | w_internal::viewValidLiterals(#A1,#A2,#A3,#A4,#A5,#A6,#A7,#A8,#A9,#A10,#A11,#A12,#A13,#A14,#A15,#A16) |
545 | |
546 | #define W_PARAM_TOSTRING_REMOVE_SCOPE(...) W_MACRO_MSVC_EMPTY W_MACRO_MSVC_DELAY(W_PARAM_TOSTRING2_REMOVE_SCOPE,__VA_ARGS__ ,,,,,,,,,,,,,,,,) |
547 | #define W_PARAM_TOSTRING2_REMOVE_SCOPE(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,...) \ |
548 | w_internal::viewValidTails< \ |
549 | w_internal::removedScopeSize(#A1), w_internal::removedScopeSize(#A2), w_internal::removedScopeSize(#A3), \ |
550 | w_internal::removedScopeSize(#A4), w_internal::removedScopeSize(#A5), w_internal::removedScopeSize(#A6), \ |
551 | w_internal::removedScopeSize(#A7), w_internal::removedScopeSize(#A8), w_internal::removedScopeSize(#A9), \ |
552 | w_internal::removedScopeSize(#A10), w_internal::removedScopeSize(#A11), w_internal::removedScopeSize(#A12), \ |
553 | w_internal::removedScopeSize(#A13), w_internal::removedScopeSize(#A14), w_internal::removedScopeSize(#A15), \ |
554 | w_internal::removedScopeSize(#A16)>(#A1,#A2,#A3,#A4,#A5,#A6,#A7,#A8,#A9,#A10,#A11,#A12,#A13,#A14,#A15,#A16) |
555 | |
556 | |
557 | // remove the surrounding parentheses |
558 | #define W_MACRO_REMOVEPAREN(A) W_MACRO_DELAY(W_MACRO_REMOVEPAREN2, W_MACRO_REMOVEPAREN_HELPER A) |
559 | #define W_MACRO_REMOVEPAREN2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_MACRO_REMOVEPAREN_HELPER_##__VA_ARGS__) |
560 | #define W_MACRO_REMOVEPAREN_HELPER(...) _ , __VA_ARGS__ |
561 | #define W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER , |
562 | |
563 | // if __VA_ARGS__ is "(types), foobar" then return just the types, otherwise return nothing |
564 | #define W_OVERLOAD_TYPES(...) W_MACRO_DELAY(W_OVERLOAD_TYPES2,W_OVERLOAD_TYPES_HELPER __VA_ARGS__,) |
565 | #define W_OVERLOAD_TYPES2(A,...) W_MACRO_DELAY2(W_OVERLOAD_TYPES3, W_OVERLOAD_TYPES_HELPER_##A ...) |
566 | #define W_OVERLOAD_TYPES3(A,...) W_MACRO_EVAL A |
567 | #define W_OVERLOAD_TYPES_HELPER(...) YES(__VA_ARGS__) |
568 | #define W_OVERLOAD_TYPES_HELPER_W_OVERLOAD_TYPES_HELPER (), |
569 | #define W_OVERLOAD_TYPES_HELPER_YES(...) (__VA_ARGS__), |
570 | |
571 | #define W_OVERLOAD_RESOLVE(...) W_MACRO_DELAY(W_OVERLOAD_RESOLVE2,W_OVERLOAD_RESOLVE_HELPER __VA_ARGS__,) |
572 | #define W_OVERLOAD_RESOLVE2(A, ...) W_MACRO_DELAY2(W_MACRO_FIRST,W_OVERLOAD_RESOLVE_HELPER_##A) |
573 | #define W_OVERLOAD_RESOLVE_HELPER(...) YES(w_internal::qOverload<__VA_ARGS__>) |
574 | #define W_OVERLOAD_RESOLVE_HELPER_YES(...) (__VA_ARGS__) |
575 | #define W_OVERLOAD_RESOLVE_HELPER_W_OVERLOAD_RESOLVE_HELPER , |
576 | |
577 | |
578 | // remove the first argument if it is in parentheses" |
579 | #define W_OVERLOAD_REMOVE(...) W_MACRO_DELAY(W_OVERLOAD_REMOVE2, W_OVERLOAD_REMOVE_HELPER __VA_ARGS__) |
580 | #define W_OVERLOAD_REMOVE2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_OVERLOAD_REMOVE_HELPER_##__VA_ARGS__) |
581 | |
582 | #define W_OVERLOAD_REMOVE_HELPER(...) _ |
583 | #define W_OVERLOAD_REMOVE_HELPER_W_OVERLOAD_REMOVE_HELPER , |
584 | |
585 | #define W_RETURN(R) -> decltype(R) { return R; } |
586 | |
587 | #ifndef Q_CC_MSVC |
588 | //Define a unique integral_constant type for a given function pointer |
589 | #define W_INTEGRAL_CONSTANT_HELPER(NAME, ...) std::integral_constant<decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)), &W_ThisType::NAME> |
590 | #else |
591 | // On MSVC 2017 we trying to get a function pointer in the type cause compiler internal error, so use a simple hash function |
592 | namespace w_internal { |
593 | constexpr auto simple_hash(char const *p) { |
594 | unsigned long long h = *p; |
595 | while (*p++) h = ((h >> 8)*37ull) ^ *p ^ ((h & 0xff) << 56) ; |
596 | return h; |
597 | } |
598 | } // namespace w_internal |
599 | #define W_INTEGRAL_CONSTANT_HELPER(NAME, ...) std::integral_constant<unsigned long long, w_internal::simple_hash(#NAME #__VA_ARGS__)> |
600 | #endif |
601 | |
602 | namespace w_internal { |
603 | |
604 | /// We store state in overloads for this method. |
605 | /// This overload is found if no better overload was found. |
606 | /// All overloads are found using ADL in the QObject T |
607 | template<class State, class TPP> |
608 | void w_state(IndexBase, State, TPP); |
609 | |
610 | #if __cplusplus > 201700L |
611 | template<size_t L, class State, class TPP, size_t N , size_t M, size_t X = (N+M)/2> |
612 | constexpr size_t countBetween() { |
613 | using R = decltype(w_state(index<X>, State{}, TPP{})); |
614 | if constexpr (N==X) { |
615 | return std::is_same_v<void, R> ? N : M; |
616 | } |
617 | else if constexpr (std::is_same_v<void, R>) { |
618 | return countBetween<L, State, TPP, N, X>(); |
619 | } |
620 | else { |
621 | return countBetween<L, State, TPP, X, M>(); |
622 | } |
623 | } |
624 | template<size_t L, class State, class TPP, size_t N = 1> |
625 | constexpr size_t count() { |
626 | using R = decltype(w_state(index<N>, State{}, TPP{})); |
627 | if constexpr (std::is_same_v<void, R>) { |
628 | return countBetween<L, State, TPP, N/2, N>(); |
629 | } |
630 | else { |
631 | return count<L, State, TPP, N*2>(); |
632 | } |
633 | } |
634 | |
635 | template<size_t L, class State, class TPP> |
636 | constexpr auto stateCount = count<L, State, TPP>(); |
637 | #else |
638 | template<size_t L, class State, class TPP |
639 | , size_t N, size_t M, size_t X = (N+M)/2 |
640 | , bool noX = std::is_same<void, decltype(w_state(index<X>, State{}, TPP{}))>::value |
641 | , bool up = N==X> |
642 | struct CountBetween; |
643 | |
644 | template<size_t L, class State, class TPP, size_t N, size_t M, size_t X> |
645 | struct CountBetween<L, State, TPP, N, M, X, true, true> { |
646 | static constexpr auto value = N; |
647 | }; |
648 | template<size_t L, class State, class TPP, size_t N, size_t M, size_t X> |
649 | struct CountBetween<L, State, TPP, N, M, X, false, true> { |
650 | static constexpr auto value = M; |
651 | }; |
652 | template<size_t L, class State, class TPP, size_t N, size_t M, size_t X> |
653 | struct CountBetween<L, State, TPP, N, M, X, true, false> { |
654 | static constexpr auto value = CountBetween<L, State, TPP, N, X>::value; |
655 | }; |
656 | template<size_t L, class State, class TPP, size_t N, size_t M, size_t X> |
657 | struct CountBetween<L, State, TPP, N, M, X, false, false> { |
658 | static constexpr auto value = CountBetween<L, State, TPP, X, M>::value; |
659 | }; |
660 | |
661 | template<size_t L, class State, class TPP |
662 | , size_t N = 1 |
663 | , bool noX = std::is_same<void, decltype(w_state(index<N>, State{}, TPP{}))>::value> |
664 | struct Count; |
665 | |
666 | template<size_t L, class State, class TPP, size_t N> |
667 | struct Count<L, State, TPP, N, true> { |
668 | static constexpr auto value = CountBetween<L, State, TPP, N/2, N>::value; |
669 | }; |
670 | template<size_t L, class State, class TPP, size_t N> |
671 | struct Count<L, State, TPP, N, false> { |
672 | static constexpr auto value = Count<L, State, TPP, N*2>::value; |
673 | }; |
674 | |
675 | template<size_t L, class State, class TPP> |
676 | constexpr auto stateCount = Count<L, State, TPP>::value; |
677 | #endif |
678 | |
679 | struct SlotStateTag {}; |
680 | struct SignalStateTag {}; |
681 | struct MethodStateTag {}; |
682 | struct ConstructorStateTag {}; |
683 | struct PropertyStateTag {}; |
684 | struct EnumStateTag {}; |
685 | struct ClassInfoStateTag {}; |
686 | struct InterfaceStateTag {}; |
687 | |
688 | } // namespace w_internal |
689 | |
690 | #define W_OBJECT_COMMON(TYPE) \ |
691 | using W_ThisType = TYPE; \ |
692 | static constexpr auto W_UnscopedName = w_internal::viewLiteral(#TYPE); /* so we don't repeat it in W_CONSTRUCTOR */ \ |
693 | friend struct w_internal::FriendHelper; \ |
694 | template<typename W_Flag> static inline constexpr int w_flagAlias(W_Flag) { return 0; } \ |
695 | public: \ |
696 | struct W_MetaObjectCreatorHelper; |
697 | |
698 | #define W_STATE_APPEND(STATE, ...) \ |
699 | friend constexpr auto w_state(w_internal::Index<w_internal::stateCount<__COUNTER__, w_internal::STATE##Tag, W_ThisType**>>, \ |
700 | w_internal::STATE##Tag, W_ThisType**) W_RETURN((__VA_ARGS__)) |
701 | #define W_STATE_APPEND_NS(STATE, ...) \ |
702 | static constexpr auto w_state(w_internal::Index<w_internal::stateCount<__COUNTER__, w_internal::STATE##Tag, W_ThisType**>>, \ |
703 | w_internal::STATE##Tag, W_ThisType**) W_RETURN((__VA_ARGS__)) |
704 | |
705 | // public macros |
706 | |
707 | /// \macro W_OBJECT(TYPE) |
708 | /// Like the Q_OBJECT macro, this declare that the object might have signals, slots or properties. |
709 | /// Must contains the class name as a parameter and need to be put before any other W_ macro in the class. |
710 | #define W_OBJECT(TYPE) \ |
711 | W_OBJECT_COMMON(TYPE) \ |
712 | public: \ |
713 | using W_BaseType = std::remove_reference_t<decltype(\ |
714 | w_internal::getParentObjectHelper(&W_ThisType::qt_metacast))>; \ |
715 | Q_OBJECT \ |
716 | QT_ANNOTATE_CLASS(qt_fake, "") |
717 | |
718 | /// \macro W_GADGET(TYPE) |
719 | /// Like the Q_GADGET macro, this declare that the object might have properties. |
720 | /// Must contains the class name as a parameter and need to be put before any other W_ macro in the class. |
721 | #define W_GADGET(TYPE) \ |
722 | W_OBJECT_COMMON(TYPE) \ |
723 | Q_GADGET \ |
724 | QT_ANNOTATE_CLASS(qt_fake, "") |
725 | |
726 | /// \macro W_NAMESPACE(NAMESPACE) |
727 | /// Like the Q_GADGET macro, this declare that the object might have properties. |
728 | /// Must contains the class name as a parameter and need to be put before any other W_ macro in the class. |
729 | #define W_NAMESPACE(NAMESPACE) \ |
730 | Q_NAMESPACE \ |
731 | struct W_MetaObjectCreatorHelper; \ |
732 | struct W_ThisType { \ |
733 | using W_MetaObjectCreatorHelper = NAMESPACE::W_MetaObjectCreatorHelper; \ |
734 | static constexpr auto qt_static_metacall = nullptr; \ |
735 | }; \ |
736 | static constexpr auto W_UnscopedName = w_internal::viewLiteral(#NAMESPACE); \ |
737 | template<typename W_Flag> static inline constexpr int w_flagAlias(W_Flag) { Q_UNUSED(W_UnscopedName) return 0; } \ |
738 | QT_ANNOTATE_CLASS(qt_fake, "") |
739 | |
740 | /// \macro W_SLOT( <slot name> [, (<parameters types>) ] [, <flags>]* ) |
741 | /// |
742 | /// The W_SLOT macro needs to be put after the slot declaration. |
743 | /// |
744 | /// The W_SLOT macro can optionally have a list of parameter types as second argument to disambiguate |
745 | /// overloads or use types that are not registered with W_REGISTER_ARGTYPE. The list of parameter |
746 | /// need to be within parentheses (even if there is 0 or 1 argument). |
747 | /// |
748 | /// The W_SLOT macro can have flags: |
749 | /// - Specifying the the access: W_Access::Protected, W_Access::Private |
750 | /// or W_Access::Public. (By default, it is auto-detected from the location of this macro.) |
751 | /// - W_Compat: for deprecated methods (equivalent of Q_MOC_COMPAT) |
752 | #define W_SLOT(...) W_MACRO_MSVC_EXPAND(W_SLOT2(__VA_ARGS__, w_internal::W_EmptyFlag)) |
753 | #define W_SLOT2(NAME, ...) \ |
754 | W_STATE_APPEND(SlotState, w_internal::makeMetaSlotInfo( \ |
755 | W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), w_internal::viewLiteral(#NAME), \ |
756 | W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)(), \ |
757 | W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \ |
758 | W_OVERLOAD_REMOVE(__VA_ARGS__))) \ |
759 | static inline void w_GetAccessSpecifierHelper(W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)) {} |
760 | |
761 | /// \macro W_INVOKABLE( <slot name> [, (<parameters types>) ] [, <flags>]* ) |
762 | /// Exactly like W_SLOT but for Q_INVOKABLE methods. |
763 | #define W_INVOKABLE(...) W_MACRO_MSVC_EXPAND(W_INVOKABLE2(__VA_ARGS__, w_internal::W_EmptyFlag)) |
764 | #define W_INVOKABLE2(NAME, ...) \ |
765 | W_STATE_APPEND(MethodState, w_internal::makeMetaMethodInfo( \ |
766 | W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), w_internal::viewLiteral(#NAME), \ |
767 | W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)(), \ |
768 | W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \ |
769 | W_OVERLOAD_REMOVE(__VA_ARGS__))) \ |
770 | static inline void w_GetAccessSpecifierHelper(W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)) {} |
771 | |
772 | /// <signal signature> |
773 | /// \macro W_SIGNAL(<signal name> [, (<parameter types>) ] , <parameter names> ) |
774 | /// |
775 | /// Unlike W_SLOT, W_SIGNAL must be placed directly after the signal signature declaration. |
776 | /// There should not be a semi colon between the signal signature and the macro |
777 | /// |
778 | /// Like W_SLOT, there can be the types of the parametter as a second argument, within parentheses. |
779 | /// You must then follow with the parameter names |
780 | /// |
781 | /// Note about exported classes: since the signal is inline, GCC won't export it when compiling |
782 | /// with -fvisibility-inlines-hidden (which is the default), so connecting using pointer to member |
783 | /// functions won't work accross library boundaries. You need to explicitly export the signal with |
784 | /// your MYLIB_EXPORT macro in front of the signal declaration. |
785 | #define W_SIGNAL(...) W_MACRO_MSVC_EXPAND(W_SIGNAL2(__VA_ARGS__ , 0)) |
786 | #define W_SIGNAL2(NAME, ...) \ |
787 | { /* W_SIGNAL need to be placed directly after the signal declaration, without semicolon. */\ |
788 | using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \ |
789 | return w_internal::SignalImplementation<w_SignalType, W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \ |
790 | } \ |
791 | static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \ |
792 | w_internal::stateCount<__COUNTER__, w_internal::SignalStateTag, W_ThisType**>; \ |
793 | friend constexpr auto w_state(w_internal::Index<W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>, w_internal::SignalStateTag, W_ThisType**) \ |
794 | W_RETURN(w_internal::makeMetaSignalInfo( \ |
795 | W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), w_internal::viewLiteral(#NAME), \ |
796 | W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)(), \ |
797 | W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__)))) \ |
798 | static inline void w_GetAccessSpecifierHelper(W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)) {} |
799 | |
800 | /// \macro W_SIGNAL_COMPAT |
801 | /// Same as W_SIGNAL, but set the W_Compat flag |
802 | #define W_SIGNAL_COMPAT(...) W_MACRO_MSVC_EXPAND(W_SIGNAL_COMPAT2(__VA_ARGS__, 0)) |
803 | #define W_SIGNAL_COMPAT2(NAME, ...) \ |
804 | { \ |
805 | using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \ |
806 | return w_internal::SignalImplementation<w_SignalType, W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \ |
807 | } \ |
808 | static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \ |
809 | w_internal::stateCount<__COUNTER__, w_internal::SignalStateTag, W_ThisType**>; \ |
810 | friend constexpr auto w_state(w_internal::Index<W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>, w_internal::SignalStateTag, W_ThisType**) \ |
811 | W_RETURN(w_internal::makeMetaSignalInfo( \ |
812 | W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), w_internal::viewLiteral(#NAME), \ |
813 | W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)(), \ |
814 | W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__)), W_Compat)) \ |
815 | static inline void w_GetAccessSpecifierHelper(W_INTEGRAL_CONSTANT_HELPER(NAME, __VA_ARGS__)) {} |
816 | |
817 | /// \macro W_CONSTRUCTOR(<parameter types>) |
818 | /// Declares that this class can be constructed with this list of argument. |
819 | /// Equivalent to Q_INVOKABLE constructor. |
820 | /// One can have W_CONSTRUCTOR() for the default constructor even if it is implicit. |
821 | #define W_CONSTRUCTOR(...) \ |
822 | W_STATE_APPEND(ConstructorState, \ |
823 | w_internal::makeMetaConstructorInfo<__VA_ARGS__>(W_UnscopedName)) |
824 | |
825 | |
826 | /// \macro W_PROPERTY(<type>, <name> [, <flags>]*) |
827 | /// |
828 | /// Declare a property <name> with the type <type>. |
829 | /// The flags can be function pointers that are detected to be setter, getters, notify signal or |
830 | /// other flags. Use the macro READ, WRITE, MEMBER, ... for the flag so you can write W_PROPERTY |
831 | /// just like in a Q_PROPERTY. The only difference with Q_PROPERTY would be the semicolon before the |
832 | /// name. |
833 | /// W_PROPERTY need to be put after all the setters, getters, signals and members have been declared. |
834 | /// |
835 | /// <type> can optionally be put in parentheses, if you have a type containing a comma |
836 | #define W_PROPERTY(...) W_MACRO_MSVC_EXPAND(W_PROPERTY2(__VA_ARGS__)) // expands the READ, WRITE, and other sub marcos |
837 | #define W_PROPERTY2(TYPE, NAME, ...) \ |
838 | W_STATE_APPEND(PropertyState, \ |
839 | w_internal::makeMetaPropertyInfo<W_MACRO_REMOVEPAREN(TYPE)>(\ |
840 | w_internal::viewLiteral(#NAME), w_internal::viewLiteral(W_MACRO_STRIGNIFY(W_MACRO_REMOVEPAREN(TYPE))), __VA_ARGS__)) |
841 | |
842 | #define WRITE , &W_ThisType:: |
843 | #define READ , &W_ThisType:: |
844 | #define NOTIFY , W_Notify, &W_ThisType:: |
845 | #define RESET , W_Reset, &W_ThisType:: |
846 | #define MEMBER , &W_ThisType:: |
847 | #define CONSTANT , W_Constant |
848 | #define FINAL , W_Final |
849 | |
850 | #undef Q_PRIVATE_PROPERTY // the official macro is not a variadic macro, and the coma in READ would break it |
851 | #define Q_PRIVATE_PROPERTY(...) |
852 | |
853 | /// \macro W_ENUM(<name>, <values>) |
854 | /// Similar to Q_ENUM, but one must also manually write all the values. |
855 | #define W_ENUM(NAME, ...) \ |
856 | W_STATE_APPEND(EnumState, w_internal::makeMetaEnumInfo<NAME,false>( \ |
857 | w_internal::viewLiteral(#NAME), w_flagAlias(NAME{}), \ |
858 | w_internal::enum_sequence<NAME,__VA_ARGS__>{}, W_PARAM_TOSTRING_REMOVE_SCOPE(__VA_ARGS__))) \ |
859 | Q_ENUM(NAME) |
860 | |
861 | |
862 | /// \macro W_ENUM_NS(<name>, <values>) |
863 | /// Similar to Q_ENUM_NS, like W_ENUM |
864 | #define W_ENUM_NS(NAME, ...) \ |
865 | W_STATE_APPEND_NS(EnumState, w_internal::makeMetaEnumInfo<NAME,false>( \ |
866 | w_internal::viewLiteral(#NAME), w_flagAlias(NAME{}), \ |
867 | w_internal::enum_sequence<NAME,__VA_ARGS__>{}, W_PARAM_TOSTRING_REMOVE_SCOPE(__VA_ARGS__))) \ |
868 | Q_ENUM_NS(NAME) |
869 | |
870 | /// \macro W_FLAG(<name>, <values>) |
871 | /// Similar to Q_FLAG, but one must also manually write all the values. |
872 | #define W_FLAG(NAME, ...) \ |
873 | W_STATE_APPEND(EnumState, w_internal::makeMetaEnumInfo<w_internal::QEnumOrQFlags<NAME>::Type,true>( \ |
874 | w_internal::viewLiteral(#NAME), w_flagAlias(NAME{}), \ |
875 | w_internal::enum_sequence<w_internal::QEnumOrQFlags<NAME>::Type,__VA_ARGS__>{}, \ |
876 | W_PARAM_TOSTRING_REMOVE_SCOPE(__VA_ARGS__))) \ |
877 | Q_FLAG(NAME) |
878 | |
879 | /// \macro W_FLAG_NS(<name>, <values>) |
880 | /// Similar to Q_FLAG_NS, like W_FLAG. |
881 | #define W_FLAG_NS(NAME, ...) \ |
882 | W_STATE_APPEND_NS(EnumState, w_internal::makeMetaEnumInfo<w_internal::QEnumOrQFlags<NAME>::Type,true>( \ |
883 | w_internal::viewLiteral(#NAME), w_flagAlias(NAME{}), \ |
884 | w_internal::enum_sequence<w_internal::QEnumOrQFlags<NAME>::Type,__VA_ARGS__>{}, \ |
885 | W_PARAM_TOSTRING_REMOVE_SCOPE(__VA_ARGS__))) \ |
886 | Q_FLAG_NS(NAME) |
887 | |
888 | /// Same as Q_CLASSINFO. Note, Q_CLASSINFO_NS is required for namespace |
889 | #define W_CLASSINFO(A, B) \ |
890 | W_STATE_APPEND(ClassInfoState, \ |
891 | std::pair<w_internal::StringView, w_internal::StringView>{ w_internal::viewLiteral(A), w_internal::viewLiteral(B) }) |
892 | |
893 | /// Same as Q_CLASSINFO, but within a namespace |
894 | #define W_CLASSINFO_NS(A, B) \ |
895 | W_STATE_APPEND_NS(ClassInfoState, \ |
896 | std::pair<w_internal::StringView, w_internal::StringView>{ w_internal::viewLiteral(A), w_internal::viewLiteral(B) }) |
897 | |
898 | /// Same as Q_INTERFACE |
899 | #define W_INTERFACE(A) \ |
900 | W_STATE_APPEND(InterfaceState, static_cast<A*>(nullptr)) |
901 | |
902 | /// Same as Q_DECLARE_FLAGS |
903 | #define W_DECLARE_FLAGS(Flags, Enum) \ |
904 | Q_DECLARE_FLAGS(Flags, Enum) \ |
905 | static inline constexpr w_internal::StringView w_flagAlias(Flags) { return w_internal::viewLiteral(#Enum); } |
906 | |
907 | /// \macro W_REGISTER_ARGTYPE(TYPE) |
908 | /// Registers TYPE so it can be used as a parameter of a signal/slot or return value. |
909 | /// The normalized signature must be used. |
910 | /// Note: This does not imply Q_DECLARE_METATYPE, and Q_DECLARE_METATYPE does not imply this |
911 | namespace w_internal { template<typename T> struct W_TypeRegistery { enum { registered = false }; }; } |
912 | #define W_REGISTER_ARGTYPE(...) namespace w_internal { \ |
913 | template<> struct W_TypeRegistery<__VA_ARGS__> { \ |
914 | enum { registered = true }; \ |
915 | static constexpr auto name = viewLiteral(#__VA_ARGS__); \ |
916 | };} |
917 | W_REGISTER_ARGTYPE(char*) |
918 | W_REGISTER_ARGTYPE(const char*) |
919 | |
920 | #else // Q_MOC_RUN |
921 | // just to avoid parse errors when moc is run over things that it should ignore |
922 | #define W_SIGNAL(...) ; |
923 | #define W_SIGNAL_COMPAT(...) ; |
924 | #define W_PROPERTY(...) |
925 | #define W_SLOT(...) |
926 | #define W_CLASSINFO(...) |
927 | #define W_INTERFACE(...) |
928 | #define W_CONSTRUCTOR(...) |
929 | #define W_FLAG(...) |
930 | #define W_ENUM(...) |
931 | #define W_DECLARE_FLAGS(...) |
932 | #endif |
933 | |