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#if !defined(__cpp_constexpr) || __cpp_constexpr < 201304
32#error Verdigris requires C++14 relaxed constexpr
33#endif
34
35namespace w_internal {
36using std::index_sequence; // From C++14, make sure to enable the C++14 option in your compiler
37
38/* The default std::make_index_sequence from libstdc++ is recursing O(N) times which is reaching
39 recursion limits level for big strings. This implementation has only O(log N) recursion */
40template<size_t... I1, size_t... I2>
41index_sequence<I1... , (I2 +(sizeof...(I1)))...>
42make_index_sequence_helper_merge(index_sequence<I1...>, index_sequence<I2...>);
43
44template<int N> struct make_index_sequence_helper {
45 using part1 = typename make_index_sequence_helper<(N+1)/2>::result;
46 using part2 = typename make_index_sequence_helper<N/2>::result;
47 using result = decltype(make_index_sequence_helper_merge(part1(), part2()));
48};
49template<> struct make_index_sequence_helper<1> { using result = index_sequence<0>; };
50template<> struct make_index_sequence_helper<0> { using result = index_sequence<>; };
51template<int N> using make_index_sequence = typename make_index_sequence_helper<N>::result;
52
53/* workaround for MSVC bug that can't do decltype(xxx)::foo when xxx is dependent of a template */
54template<typename T> using identity_t = T;
55
56/**
57 * In this namespace we find the implementation of a template binary tree container
58 * It has a similar API than std::tuple, but is stored in a binary way.
59 * the libstdc++ std::tuple recurse something like 16*N for a tuple of N elements. (Because the copy
60 * constructor uses traits for stuff like noexcept.) Which means we are quickly reaching the
61 * implementation limit of recursion. (Cannot have more than ~16 items in a tuple)
62 * Also, a linear tuple happens to lead to very slow compilation times.
63 *
64 * So a std::tuple<T1, T2, T3, T4> is represented by a
65 * binary::tree<Node<Node<Leaf<T1>, Leaf<T2>>, Node<Leaf<T3>, Leaf<T4>>>
66 */
67namespace binary {
68
69 template <typename T> struct Leaf {
70 T data;
71 static constexpr int Depth = 0;
72 static constexpr int Count = 1;
73 static constexpr bool Balanced = true;
74 };
75
76 template <class A, class B> struct Node {
77 A a;
78 B b;
79 static constexpr int Count = A::Count + B::Count;
80 static constexpr int Depth = A::Depth + 1;
81 static constexpr bool Balanced = A::Depth == B::Depth && B::Balanced;
82 };
83
84 /** Add the node 'N' to the tree 'T' (helper for tree_append) */
85 template <class T, typename N, bool Balanced = T::Balanced > struct Add {
86 typedef Node<T, Leaf<N> > Result;
87 static constexpr Result add(T t, N n) { return {t, {n} }; }
88 };
89 template <class A, class B, typename N> struct Add<Node<A, B>, N, false> {
90 typedef Node<A, typename Add<B, N>::Result > Result;
91 static constexpr Result add(Node<A, B> t, N n) { return {t.a , Add<B, N>::add(t.b, n) }; }
92 };
93
94 /** Add the node 'N' to the tree 'T', on the left (helper for tree_prepend) */
95 template <class T, typename N, bool Balanced = T::Balanced > struct AddPre {
96 typedef Node<Leaf<N> , T > Result;
97 static constexpr Result add(T t, N n) { return {{n}, t}; }
98 };
99 template <class A, class B, typename N> struct AddPre<Node<A, B>, N, false> {
100 typedef Node<typename AddPre<A, N>::Result, B > Result;
101 static constexpr Result add(Node<A, B> t, N n) { return {AddPre<A, N>::add(t.a, n) , t.b }; }
102 };
103
104 /** helper for binary::get<> */
105 template <class T, int I, typename = void> struct Get;
106 template <class N> struct Get<Leaf<N>, 0>
107 { static constexpr N get(Leaf<N> t) { return t.data; } };
108 template <class A, class B, int I> struct Get<Node<A,B>, I, std::enable_if_t<(A::Count <= I)>>
109 { static constexpr auto get(Node<A,B> t) { return Get<B,I - A::Count>::get(t.b); } };
110 template <class A, class B, int I> struct Get<Node<A,B>, I, std::enable_if_t<(A::Count > I)>>
111 { static constexpr auto get(Node<A,B> t) { return Get<A,I>::get(t.a); } };
112
113 /** helper for tree_tail */
114 template<typename A, typename B> struct Tail;
115 template<typename A, typename B> struct Tail<Leaf<A>, B> {
116 using Result = B;
117 static constexpr B tail(Node<Leaf<A>,B> t) { return t.b; }
118 };
119 template<typename A, typename B, typename C> struct Tail<Node<A,B>, C> {
120 using Result = Node<typename Tail<A,B>::Result, C>;
121 static constexpr Result tail(Node<Node<A,B>, C> t) { return { Tail<A,B>::tail(t.a) , t.b }; }
122 };
123
124 /** An equivalent of std::tuple hold in a binary tree for faster compile time */
125 template<typename T = void> struct tree {
126 static constexpr int size = T::Count;
127 T root;
128 };
129 template<> struct tree<> { static constexpr int size = 0; };
130
131 /**
132 * tree_append(tree, T): append an element at the end of the tree.
133 */
134 template<typename T>
135 constexpr tree<Leaf<T>> tree_append(tree<>, T n)
136 { return {{n}}; }
137 template<typename Root, typename T>
138 constexpr tree<typename Add<Root,T>::Result> tree_append(tree<Root> t, T n)
139 { return {Add<Root,T>::add(t.root,n)}; }
140
141 /**
142 * tree_append(tree, T): prepend an element at the beginning of the tree.
143 */
144 template<typename T>
145 constexpr tree<Leaf<T>> tree_prepend(tree<>, T n)
146 { return {{n}}; }
147 template<typename Root, typename T>
148 constexpr tree<typename AddPre<Root,T>::Result> tree_prepend(tree<Root> t, T n)
149 { return {AddPre<Root,T>::add(t.root,n)}; }
150
151 /**
152 * get<N>(tree): Returns the element from the tree at index N.
153 */
154 template<int N, typename Root> constexpr auto get(tree<Root> t)
155 { return Get<Root, N>::get(t.root); }
156
157 /**
158 * tree_tail(tree): Returns a tree with the first element removed.
159 */
160 template<typename A, typename B>
161 constexpr tree<typename Tail<A,B>::Result> tree_tail(tree<Node<A, B>> t)
162 { return { Tail<A,B>::tail(t.root) }; }
163 template<typename N>
164 constexpr tree<> tree_tail(tree<Leaf<N>>) { return {}; }
165 constexpr tree<> tree_tail(tree<>) { return {}; }
166
167 /**
168 * tree_head(tree): same as get<O> but return something invalid in case the tuple is too small.
169 */
170 template<typename T> constexpr auto tree_head(tree<T> t) { return get<0>(t); }
171 constexpr auto tree_head(tree<void>) { struct _{}; return _{}; }
172 template<typename T> constexpr auto tree_head(T) { struct _{}; return _{}; }
173
174 template<int I, typename T> using tree_element_t = decltype(get<I>(std::declval<T>()));
175
176 /**
177 * tree_cat(tree1, tree2, ....): concatenate trees (like tuple_cat)
178 */
179 // FIXME: Should we balance?
180 template<class A, class B>
181 constexpr tree<Node<A,B>> tree_cat(tree<A> a, tree<B> b) { return { { a.root, b.root } }; }
182 template<class A>
183 constexpr tree<A> tree_cat(tree<>, tree<A> a) { return a; }
184 template<class A>
185 constexpr tree<A> tree_cat(tree<A> a, tree<>) { return a; }
186 constexpr tree<> tree_cat(tree<>, tree<>) { return {}; }
187 template<class A, class B, class C, class...D>
188 constexpr auto tree_cat(A a, B b, C c, D... d) { return tree_cat(a, tree_cat(b, c, d...)); }
189} // namespace binary
190
191
192/** Compute the sum of many integers */
193constexpr int sums() { return 0; }
194template<typename... Args>
195constexpr int sums(int i, Args... args) { return i + sums(args...); }
196// This indirection is required to work around a MSVC bug. (See https://github.com/woboq/verdigris/issues/6 )
197template <int ...Args>
198constexpr int summed = sums(Args...);
199
200/*
201 * Helpers to play with static strings
202 */
203
204/** A compile time character array of size N */
205template<int N> using StaticStringArray = const char [N];
206
207/** Represents a string of size N (N includes the '\0' at the end) */
208template<int N, typename = make_index_sequence<N>> struct StaticString;
209template<int N, std::size_t... I> struct StaticString<N, std::index_sequence<I...>>
210{
211 StaticStringArray<N> data;
212 constexpr StaticString(StaticStringArray<N> &d) : data{ (d[I])... } { }
213 static constexpr int size = N;
214 constexpr char operator[](int p) const { return data[p]; }
215};
216template <int N> constexpr StaticString<N> makeStaticString(StaticStringArray<N> &d) { return {d}; }
217
218/** A list containing many StaticString with possibly different sizes */
219template<typename T = void> using StaticStringList = binary::tree<T>;
220
221/** Make a StaticStringList out of many char array */
222constexpr StaticStringList<> makeStaticStringList() { return {}; }
223template<typename... T>
224constexpr StaticStringList<> makeStaticStringList(StaticStringArray<1> &, T...)
225{ return {}; }
226template<int N, typename... T>
227constexpr auto makeStaticStringList(StaticStringArray<N> &h, T&...t)
228{ return binary::tree_prepend(makeStaticStringList(t...), StaticString<N>(h)); }
229
230/** Add a string in a StaticStringList */
231template<int L, typename T>
232constexpr auto addString(const StaticStringList<T> &l, const StaticString<L> & s) {
233 return binary::tree_append(l, s);
234}
235
236
237/*-----------*/
238
239 // From qmetaobject_p.h
240enum class PropertyFlags {
241 Invalid = 0x00000000,
242 Readable = 0x00000001,
243 Writable = 0x00000002,
244 Resettable = 0x00000004,
245 EnumOrFlag = 0x00000008,
246 StdCppSet = 0x00000100,
247 // Override = 0x00000200,
248 Constant = 0x00000400,
249 Final = 0x00000800,
250 Designable = 0x00001000,
251 ResolveDesignable = 0x00002000,
252 Scriptable = 0x00004000,
253 ResolveScriptable = 0x00008000,
254 Stored = 0x00010000,
255 ResolveStored = 0x00020000,
256 Editable = 0x00040000,
257 ResolveEditable = 0x00080000,
258 User = 0x00100000,
259 ResolveUser = 0x00200000,
260 Notify = 0x00400000,
261 Revisioned = 0x00800000
262};
263constexpr uint operator|(uint a, PropertyFlags b) { return a | uint(b); }
264
265/** w_number<I> is a helper to implement state */
266template<int N = 255> struct w_number : public w_number<N - 1> {
267 static constexpr int value = N;
268 static constexpr w_number<N-1> prev() { return {}; }
269};
270template<> struct w_number<0> { static constexpr int value = 0; };
271
272template <int N> struct W_MethodFlags { static constexpr int value = N; };
273} // w_internal
274
275/** Objects that can be used as flags in the W_SLOT macro */
276
277// Mirror of QMetaMethod::Access
278namespace W_Access {
279/* // From qmetaobject_p.h MethodFlags
280 AccessPrivate = 0x00,
281 AccessProtected = 0x01,
282 AccessPublic = 0x02,
283 AccessMask = 0x03, //mask
284 */
285 constexpr w_internal::W_MethodFlags<0x00> Public{};
286 constexpr w_internal::W_MethodFlags<0x01> Protected{};
287 constexpr w_internal::W_MethodFlags<0x02> Private{}; // Note: Public and Private are reversed so Public can be the default
288}
289
290// Mirror of QMetaMethod::MethodType
291namespace W_MethodType {
292 /* // From qmetaobject_p.h MethodFlags
293 MethodMethod = 0x00,
294 MethodSignal = 0x04,
295 MethodSlot = 0x08,
296 MethodConstructor = 0x0c,
297 MethodTypeMask = 0x0c,
298 */
299 constexpr w_internal::W_MethodFlags<0x00> Method{};
300 constexpr w_internal::W_MethodFlags<0x04> Signal{};
301 constexpr w_internal::W_MethodFlags<0x08> Slot{};
302 constexpr w_internal::W_MethodFlags<0x0c> Constructor{};
303}
304
305/*
306MethodCompatibility = 0x10,
307MethodCloned = 0x20,
308MethodScriptable = 0x40,
309MethodRevisioned = 0x80
310*/
311constexpr w_internal::W_MethodFlags<0x10> W_Compat{};
312constexpr w_internal::W_MethodFlags<0x40> W_Scriptable{};
313constexpr struct {} W_Notify{};
314constexpr struct {} W_Reset{};
315constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Constant)> W_Constant{};
316constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Final)> W_Final{};
317
318namespace w_internal {
319
320// workaround to avoid leading comma in macro that can optionaly take a flag
321struct W_RemoveLeadingComma { constexpr W_MethodFlags<0> operator+() const { return {}; } };
322template <typename T> constexpr T operator+(T &&t, W_RemoveLeadingComma) { return t; }
323constexpr W_RemoveLeadingComma W_removeLeadingComma{};
324constexpr W_MethodFlags<0> W_EmptyFlag{};
325
326/** Holds information about a method */
327template<typename F, int NameLength, int Flags, typename ParamTypes, typename ParamNames = StaticStringList<>>
328struct MetaMethodInfo {
329 F func;
330 StaticString<NameLength> name;
331 ParamTypes paramTypes;
332 ParamNames paramNames;
333 static constexpr int argCount = QtPrivate::FunctionPointer<F>::ArgumentCount;
334 static constexpr int flags = Flags;
335};
336
337// Called from the W_SLOT macro
338template<typename F, int N, typename ParamTypes, int... Flags>
339constexpr MetaMethodInfo<F, N, summed<Flags...> | W_MethodType::Slot.value, ParamTypes>
340makeMetaSlotInfo(F f, StaticStringArray<N> &name, const ParamTypes &paramTypes, W_MethodFlags<Flags>...)
341{ return { f, {name}, paramTypes, {} }; }
342
343// Called from the W_METHOD macro
344template<typename F, int N, typename ParamTypes, int... Flags>
345constexpr MetaMethodInfo<F, N, summed<Flags...> | W_MethodType::Method.value, ParamTypes>
346makeMetaMethodInfo(F f, StaticStringArray<N> &name, const ParamTypes &paramTypes, W_MethodFlags<Flags>...)
347{ return { f, {name}, paramTypes, {} }; }
348
349// Called from the W_SIGNAL macro
350template<typename F, int N, typename ParamTypes, typename ParamNames, int... Flags>
351constexpr MetaMethodInfo<F, N, summed<Flags...> | W_MethodType::Signal.value,
352 ParamTypes, ParamNames>
353makeMetaSignalInfo(F f, StaticStringArray<N> &name, const ParamTypes &paramTypes,
354 const ParamNames &paramNames, W_MethodFlags<Flags>...)
355{ return { f, {name}, paramTypes, paramNames }; }
356
357/** Holds information about a constructor */
358template<int NameLength, typename... Args> struct MetaConstructorInfo {
359 static constexpr int argCount = sizeof...(Args);
360 static constexpr int flags = W_MethodType::Constructor.value | W_Access::Public.value;
361 StaticString<NameLength> name;
362 template<int N>
363 constexpr MetaConstructorInfo<N, Args...> setName(StaticStringArray<N> &name)
364 { return { { name } }; }
365 template<typename T, std::size_t... I>
366 void createInstance(void **_a, std::index_sequence<I...>) const {
367 *reinterpret_cast<T**>(_a[0]) =
368 new T(*reinterpret_cast<std::remove_reference_t<Args> *>(_a[I+1])...);
369 }
370};
371// called from the W_CONSTRUCTOR macro
372template<typename... Args> constexpr MetaConstructorInfo<1,Args...> makeMetaConstructorInfo()
373{ return { {""} }; }
374
375/** Holds information about a property */
376template<typename Type, int NameLength, int TypeLength, typename Getter = std::nullptr_t,
377 typename Setter = std::nullptr_t, typename Member = std::nullptr_t,
378 typename Notify = std::nullptr_t, typename Reset = std::nullptr_t, int Flags = 0>
379struct MetaPropertyInfo {
380 using PropertyType = Type;
381 StaticString<NameLength> name;
382 StaticString<TypeLength> typeStr;
383 Getter getter;
384 Setter setter;
385 Member member;
386 Notify notify;
387 Reset reset;
388 static constexpr uint flags = Flags;
389
390 template <typename S> constexpr auto setGetter(const S&s) const {
391 return MetaPropertyInfo<Type, NameLength, TypeLength, S, Setter, Member, Notify, Reset,
392 Flags | PropertyFlags::Readable>
393 {name, typeStr, s, setter, member, notify, reset};
394 }
395 template <typename S> constexpr auto setSetter(const S&s) const {
396 return MetaPropertyInfo<Type, NameLength, TypeLength, Getter, S, Member, Notify, Reset,
397 Flags | PropertyFlags::Writable>
398 {name, typeStr, getter, s, member, notify, reset};
399 }
400 template <typename S> constexpr auto setMember(const S&s) const {
401 return MetaPropertyInfo<Type, NameLength, TypeLength, Getter, Setter, S, Notify, Reset,
402 Flags | PropertyFlags::Writable | PropertyFlags::Readable>
403 {name, typeStr, getter, setter, s, notify, reset};
404 }
405 template <typename S> constexpr auto setNotify(const S&s) const {
406 return MetaPropertyInfo<Type, NameLength, TypeLength, Getter, Setter, Member, S, Reset,
407 Flags | PropertyFlags::Notify>
408 { name, typeStr, getter, setter, member, s, reset};
409 }
410 template <typename S> constexpr auto setReset(const S&s) const {
411 return MetaPropertyInfo<Type, NameLength, TypeLength, Getter, Setter, Member, Notify, S,
412 Flags | PropertyFlags::Resettable>
413 { name, typeStr, getter, setter, member, notify, s};
414 }
415 template <int Flag> constexpr auto addFlag() const {
416 return MetaPropertyInfo<Type, NameLength, TypeLength, Getter, Setter, Member, Notify, Reset,
417 Flags | Flag>
418 { name, typeStr, getter, setter, member, notify, reset};
419 }
420};
421
422/** Parse a property and fill a MetaPropertyInfo (called from W_PRPERTY macro) */
423// base case
424template <typename PropInfo> constexpr auto parseProperty(const PropInfo &p) { return p; }
425// setter
426template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail>
427constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg), Tail... t)
428{ return parseProperty(p.setSetter(s) , t...); }
429#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
430template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail>
431constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg) noexcept, Tail... t)
432{ return parseProperty(p.setSetter(s) , t...); }
433#endif
434// getter
435template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
436constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(), Tail... t)
437{ return parseProperty(p.setGetter(s), t...); }
438template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
439constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const, Tail... t)
440{ return parseProperty(p.setGetter(s), t...); }
441#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
442template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
443constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() noexcept, Tail... t)
444{ return parseProperty(p.setGetter(s), t...); }
445template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
446constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const noexcept, Tail... t)
447{ return parseProperty(p.setGetter(s), t...); }
448#endif
449// member
450template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
451constexpr auto parseProperty(const PropInfo &p, Ret Obj::*s, Tail... t)
452{ return parseProperty(p.setMember(s) ,t...); }
453// notify
454template <typename PropInfo, typename F, typename... Tail>
455constexpr auto parseProperty(const PropInfo &p, decltype(W_Notify), F f, Tail... t)
456{ return parseProperty(p.setNotify(f) ,t...); }
457// reset
458template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
459constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)(), Tail... t)
460{ return parseProperty(p.setReset(s) ,t...); }
461#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
462template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
463constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)() noexcept, Tail... t)
464{ return parseProperty(p.setReset(s) ,t...); }
465#endif
466// other flags flags
467template <typename PropInfo, int Flag, typename... Tail>
468constexpr auto parseProperty(const PropInfo &p, std::integral_constant<int, Flag>, Tail... t)
469{ return parseProperty(p.template addFlag<Flag>() ,t...); }
470
471template<typename T, int N1, int N2, typename ... Args>
472constexpr auto makeMetaPropertyInfo(StaticStringArray<N1> &name, StaticStringArray<N2> &type, Args... args) {
473 MetaPropertyInfo<T, N1, N2> meta
474 { {name}, {type}, {}, {}, {}, {}, {} };
475 return parseProperty(meta, args...);
476}
477
478/** Holds information about an enum */
479template<int NameLength, typename Values_, typename Names, int Flags>
480struct MetaEnumInfo {
481 StaticString<NameLength> name;
482 Names names;
483 using Values = Values_;
484 static constexpr uint flags = Flags;
485 static constexpr auto count = Values::size();
486};
487template<typename Enum, Enum... Value> struct enum_sequence {};
488// called from W_ENUM and W_FLAG
489template<typename Enum, int Flag, int NameLength, Enum... Values, typename Names>
490constexpr MetaEnumInfo<NameLength, std::index_sequence<size_t(Values)...> , Names, Flag> makeMetaEnumInfo(
491 StaticStringArray<NameLength> &name, enum_sequence<Enum, Values...>, Names names) {
492 return { {name}, names };
493}
494
495/**
496 * Helper for the implementation of a signal.
497 * Called from the signal implementation within the W_SIGNAL macro.
498 *
499 * 'Func' is the type of the signal. 'Idx' is the signal index (relative).
500 * It is implemented as a functor so the operator() has exactly the same amount of argument of the
501 * signal so the __VA_ARGS__ works also if there is no arguments (no leading commas)
502 *
503 * There is specialization for const and non-const, and for void and non-void signals.
504 *
505 * the last argument of the operator() is an int, to workaround the ",0" required in the W_SIGNAL
506 * macro to make sure there is at least one argument for the ...
507 */
508template<typename Func, int Idx> struct SignalImplementation {};
509template<typename Obj, typename Ret, typename... Args, int Idx>
510struct SignalImplementation<Ret (Obj::*)(Args...), Idx>{
511 Obj *this_;
512 Ret operator()(Args... args, int) const {
513 Ret r{};
514 const void * a[]= { &r, (&args)... };
515 QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast<void **>(a));
516 return r;
517 }
518};
519template<typename Obj, typename... Args, int Idx>
520struct SignalImplementation<void (Obj::*)(Args...), Idx>{
521 Obj *this_;
522 void operator()(Args... args, int) {
523 const void *a[]= { nullptr, (&args)... };
524 QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast<void **>(a));
525 }
526};
527template<typename Obj, typename Ret, typename... Args, int Idx>
528struct SignalImplementation<Ret (Obj::*)(Args...) const, Idx>{
529 const Obj *this_;
530 Ret operator()(Args... args, int) const {
531 Ret r{};
532 const void * a[]= { &r, (&args)... };
533 QMetaObject::activate(const_cast<Obj*>(this_), &Obj::staticMetaObject, Idx, const_cast<void **>(a));
534 return r;
535 }
536};
537template<typename Obj, typename... Args, int Idx>
538struct SignalImplementation<void (Obj::*)(Args...) const, Idx>{
539 const Obj *this_;
540 void operator()(Args... args, int) {
541 const void *a[]= { nullptr, (&args)... };
542 QMetaObject::activate(const_cast<Obj*>(this_), &Obj::staticMetaObject, Idx, const_cast<void **>(a));
543 }
544};
545
546/**
547 * Used in the W_OBJECT macro to compute the base type.
548 * Used like this:
549 * using W_BaseType = std::remove_reference_t<decltype(getParentObjectHelper(&W_ThisType::qt_metacast))>;
550 * Since qt_metacast for W_ThisType will be declared later, the pointer to member function will be
551 * pointing to the qt_metacast of the base class, so T will be deduced to the base class type.
552 *
553 * Returns a reference so this work if T is an abstract class.
554 */
555template<typename T> T &getParentObjectHelper(void* (T::*)(const char*));
556
557// helper class that can access the private member of any class with W_OBJECT
558struct FriendHelper;
559
560} // w_internal
561
562#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
563inline namespace w_ShouldBeInQt {
564// This is already in Qt 5.7, but added in an inline namespace so it works with previous version of Qt
565template <typename... Args>
566struct QNonConstOverload
567{
568 template <typename R, typename T>
569 constexpr auto operator()(R (T::*ptr)(Args...)) const
570 { return ptr; }
571};
572template <typename... Args>
573struct QConstOverload
574{
575 template <typename R, typename T>
576 constexpr auto operator()(R (T::*ptr)(Args...) const) const
577 { return ptr; }
578};
579template <typename... Args>
580struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
581{
582 using QConstOverload<Args...>::operator();
583 using QNonConstOverload<Args...>::operator();
584
585 template <typename R>
586 constexpr auto operator()(R (*ptr)(Args...)) const
587 { return ptr; }
588};
589template <typename... Args> constexpr QOverload<Args...> qOverload = {};
590}
591
592#ifndef QT_ANNOTATE_CLASS // Was added in Qt 5.6.1
593#define QT_ANNOTATE_CLASS(...)
594#endif
595
596#endif // Qt < 5.7
597
598
599#ifdef Q_CC_MSVC
600// Workaround for MSVC: expension rules are different so we need some extra macro.
601#define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__
602#define W_MACRO_MSVC_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
603#define W_MACRO_MSVC_EMPTY /##* *##/
604#else
605#define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__
606#define W_MACRO_MSVC_DELAY(X,...) X(__VA_ARGS__)
607#define W_MACRO_MSVC_EMPTY
608#endif
609
610// Private macro helpers for macro programming
611#define W_MACRO_EMPTY
612#define W_MACRO_EVAL(...) __VA_ARGS__
613#define W_MACRO_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
614#define W_MACRO_DELAY2(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
615#define W_MACRO_TAIL(A, ...) __VA_ARGS__
616#define W_MACRO_FIRST(...) W_MACRO_MSVC_EXPAND(W_MACRO_FIRST2(__VA_ARGS__,))
617#define W_MACRO_FIRST2(A, ...) A
618#define W_MACRO_STRIGNIFY(...) W_MACRO_STRIGNIFY2(__VA_ARGS__)
619#define W_MACRO_STRIGNIFY2(...) #__VA_ARGS__
620#define W_MACRO_CONCAT(A, B) W_MACRO_CONCAT2(A,B)
621#define W_MACRO_CONCAT2(A, B) A##_##B
622
623// strignify and make a StaticStringList out of an array of arguments
624#define W_PARAM_TOSTRING(...) W_MACRO_MSVC_EMPTY W_MACRO_MSVC_DELAY(W_PARAM_TOSTRING2,__VA_ARGS__ ,,,,,,,,,,,,,,,,)
625#define W_PARAM_TOSTRING2(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,...) \
626 w_internal::makeStaticStringList(#A1,#A2,#A3,#A4,#A5,#A6,#A7,#A8,#A9,#A10,#A11,#A12,#A13,#A14,#A15,#A16)
627
628// remove the surrounding parentheses
629#define W_MACRO_REMOVEPAREN(A) W_MACRO_DELAY(W_MACRO_REMOVEPAREN2, W_MACRO_REMOVEPAREN_HELPER A)
630#define W_MACRO_REMOVEPAREN2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_MACRO_REMOVEPAREN_HELPER_##__VA_ARGS__)
631#define W_MACRO_REMOVEPAREN_HELPER(...) _ , __VA_ARGS__
632#define W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER ,
633
634// if __VA_ARGS__ is "(types), foobar" then return just the types, otherwise return nothing
635#define W_OVERLOAD_TYPES(...) W_MACRO_DELAY(W_OVERLOAD_TYPES2,W_OVERLOAD_TYPES_HELPER __VA_ARGS__,)
636#define W_OVERLOAD_TYPES2(A,...) W_MACRO_DELAY2(W_OVERLOAD_TYPES3, W_OVERLOAD_TYPES_HELPER_##A ...)
637#define W_OVERLOAD_TYPES3(A,...) W_MACRO_EVAL A
638#define W_OVERLOAD_TYPES_HELPER(...) YES(__VA_ARGS__)
639#define W_OVERLOAD_TYPES_HELPER_W_OVERLOAD_TYPES_HELPER (),
640#define W_OVERLOAD_TYPES_HELPER_YES(...) (__VA_ARGS__),
641
642#define W_OVERLOAD_RESOLVE(...) W_MACRO_DELAY(W_OVERLOAD_RESOLVE2,W_OVERLOAD_RESOLVE_HELPER __VA_ARGS__,)
643#define W_OVERLOAD_RESOLVE2(A, ...) W_MACRO_DELAY2(W_MACRO_FIRST,W_OVERLOAD_RESOLVE_HELPER_##A)
644#define W_OVERLOAD_RESOLVE_HELPER(...) YES(qOverload<__VA_ARGS__>)
645#define W_OVERLOAD_RESOLVE_HELPER_YES(...) (__VA_ARGS__)
646#define W_OVERLOAD_RESOLVE_HELPER_W_OVERLOAD_RESOLVE_HELPER ,
647
648
649// remove the first argument if it is in parentheses"
650#define W_OVERLOAD_REMOVE(...) W_MACRO_DELAY(W_OVERLOAD_REMOVE2, W_OVERLOAD_REMOVE_HELPER __VA_ARGS__)
651#define W_OVERLOAD_REMOVE2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_OVERLOAD_REMOVE_HELPER_##__VA_ARGS__)
652
653#define W_OVERLOAD_REMOVE_HELPER(...) _
654#define W_OVERLOAD_REMOVE_HELPER_W_OVERLOAD_REMOVE_HELPER ,
655
656#define W_RETURN(R) -> decltype(R) { return R; }
657
658#define W_OBJECT_COMMON(TYPE) \
659 using W_ThisType = TYPE; \
660 static constexpr auto &W_UnscopedName = #TYPE; /* so we don't repeat it in W_CONSTRUCTOR */ \
661 friend struct w_internal::FriendHelper; \
662 friend constexpr w_internal::binary::tree<> w_SlotState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
663 friend constexpr w_internal::binary::tree<> w_SignalState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
664 friend constexpr w_internal::binary::tree<> w_MethodState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
665 friend constexpr w_internal::binary::tree<> w_ConstructorState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
666 friend constexpr w_internal::binary::tree<> w_PropertyState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
667 friend constexpr w_internal::binary::tree<> w_EnumState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
668 friend constexpr w_internal::binary::tree<> w_ClassInfoState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
669 friend constexpr w_internal::binary::tree<> w_InterfaceState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
670 public: \
671 struct W_MetaObjectCreatorHelper;
672
673#if defined Q_CC_GNU && !defined Q_CC_CLANG
674// workaround gcc bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69836)
675#define W_STATE_APPEND(STATE, ...) \
676 static constexpr int W_MACRO_CONCAT(W_WORKAROUND_, __LINE__) = \
677 decltype(STATE(w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))::size+1; \
678 friend constexpr auto STATE(w_internal::w_number<W_MACRO_CONCAT(W_WORKAROUND_, __LINE__)> w_counter, W_ThisType **w_this) \
679 W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__))
680#else
681#define W_STATE_APPEND(STATE, ...) \
682 friend constexpr auto STATE(w_internal::w_number<w_internal::identity_t<decltype(STATE( \
683 w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))>::size+1> w_counter, \
684 W_ThisType **w_this) \
685 W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__))
686#endif
687#define W_STATE_APPEND_NS(STATE, ...) \
688 static constexpr auto STATE(w_internal::w_number<decltype(STATE( \
689 w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))::size+1> w_counter, \
690 W_ThisType **w_this) \
691 W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__))
692
693//
694// public macros
695
696/** \macro W_OBJECT(TYPE)
697 * Like the Q_OBJECT macro, this declare that the object might have signals, slots or properties.
698 * Must contains the class name as a parameter and need to be put before any other W_ macro in the class.
699 */
700#define W_OBJECT(TYPE) \
701 W_OBJECT_COMMON(TYPE) \
702 public: \
703 using W_BaseType = std::remove_reference_t<decltype(\
704 w_internal::getParentObjectHelper(&W_ThisType::qt_metacast))>; \
705 Q_OBJECT \
706 QT_ANNOTATE_CLASS(qt_fake, "")
707
708/** \macro W_GADGET(TYPE)
709 * Like the Q_GADGET macro, this declare that the object might have properties.
710 * Must contains the class name as a parameter and need to be put before any other W_ macro in the class.
711 */
712#define W_GADGET(TYPE) \
713 W_OBJECT_COMMON(TYPE) \
714 Q_GADGET \
715 QT_ANNOTATE_CLASS(qt_fake, "")
716
717/** \macro W_NAMESPACE(NAMESPACE)
718 * Like the Q_GADGET macro, this declare that the object might have properties.
719 * Must contains the class name as a parameter and need to be put before any other W_ macro in the class.
720 */
721#define W_NAMESPACE(NAMESPACE) \
722 Q_NAMESPACE \
723 struct W_MetaObjectCreatorHelper; \
724 struct W_ThisType { \
725 using W_MetaObjectCreatorHelper = NAMESPACE::W_MetaObjectCreatorHelper; \
726 static constexpr auto qt_static_metacall = nullptr; \
727 }; \
728 constexpr auto &W_UnscopedName = #NAMESPACE; \
729 static constexpr w_internal::binary::tree<> w_SlotState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
730 static constexpr w_internal::binary::tree<> w_SignalState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
731 static constexpr w_internal::binary::tree<> w_MethodState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
732 static constexpr w_internal::binary::tree<> w_ConstructorState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
733 static constexpr w_internal::binary::tree<> w_PropertyState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
734 static constexpr w_internal::binary::tree<> w_EnumState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
735 static constexpr w_internal::binary::tree<> w_ClassInfoState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
736 static constexpr w_internal::binary::tree<> w_InterfaceState(w_internal::w_number<0>, W_ThisType**) { return {}; } \
737 QT_ANNOTATE_CLASS(qt_fake, "")
738
739/**
740 * 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 (the default)
751 * - W_Compat: for deprecated methods (equivalent of Q_MOC_COMPAT)
752 */
753#define W_SLOT(...) W_MACRO_MSVC_EXPAND(W_SLOT2(__VA_ARGS__, w_internal::W_EmptyFlag))
754#define W_SLOT2(NAME, ...) \
755 W_STATE_APPEND(w_SlotState, w_internal::makeMetaSlotInfo( \
756 W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
757 W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \
758 W_OVERLOAD_REMOVE(__VA_ARGS__) +w_internal::W_removeLeadingComma))
759
760/**
761 * W_INVOKABLE( <slot name> [, (<parameters types>) ] [, <flags>]* )
762 * Exactly like W_SLOT but for Q_INVOKABLE methods.
763 */
764#define W_INVOKABLE(...) W_MACRO_MSVC_EXPAND(W_INVOKABLE2(__VA_ARGS__, w_internal::W_EmptyFlag))
765#define W_INVOKABLE2(NAME, ...) \
766 W_STATE_APPEND(w_MethodState, w_internal::makeMetaMethodInfo( \
767 W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
768 W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \
769 W_OVERLOAD_REMOVE(__VA_ARGS__) +w_internal::W_removeLeadingComma))
770
771/**
772 * <signal signature>
773 * 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#define W_SIGNAL(...) W_MACRO_MSVC_EXPAND(W_SIGNAL2(__VA_ARGS__ , 0))
782#define W_SIGNAL2(NAME, ...) \
783 { /* W_SIGNAL need to be placed directly after the signal declaration, without semicolon. */\
784 using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \
785 return w_internal::SignalImplementation<w_SignalType, W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \
786 } \
787 static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \
788 decltype(w_SignalState(w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))::size; \
789 friend constexpr auto w_SignalState(w_internal::w_number<W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) + 1> w_counter, W_ThisType **w_this) \
790 W_RETURN(w_internal::binary::tree_append(w_SignalState(w_counter.prev(), w_this), \
791 w_internal::makeMetaSignalInfo( \
792 W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
793 W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__)))))
794
795/** \macro W_SIGNAL_COMPAT
796 * Same as W_SIGNAL, but set the W_Compat flag
797 */
798#define W_SIGNAL_COMPAT(...) W_MACRO_MSVC_EXPAND(W_SIGNAL_COMPAT2(__VA_ARGS__, 0))
799#define W_SIGNAL_COMPAT2(NAME, ...) \
800 { \
801 using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \
802 return w_internal::SignalImplementation<w_SignalType, W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__)>{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \
803 } \
804 static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \
805 decltype(w_SignalState(w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))::size; \
806 friend constexpr auto w_SignalState(w_internal::w_number<W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) + 1> w_counter, W_ThisType **w_this) \
807 W_RETURN(w_internal::binary::tree_append(w_SignalState(w_counter.prev(), w_this), \
808 w_internal::makeMetaSignalInfo( \
809 W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
810 W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__)), W_Compat)))
811
812/** W_CONSTRUCTOR(<parameter types>)
813 * Declares that this class can be constructed with this list of argument.
814 * Equivalent to Q_INVOKABLE constructor.
815 * One can have W_CONSTRUCTOR() for the default constructor even if it is implicit.
816 */
817#define W_CONSTRUCTOR(...) \
818 W_STATE_APPEND(w_ConstructorState, \
819 w_internal::makeMetaConstructorInfo<__VA_ARGS__>().setName(W_UnscopedName))
820
821
822/** W_PROPERTY(<type>, <name> [, <flags>]*)
823 *
824 * Declare a property <name> with the type <type>.
825 * The flags can be function pointers that are detected to be setter, getters, notify signal or
826 * other flags. Use the macro READ, WRITE, MEMBER, ... for the flag so you can write W_PROPERTY
827 * just like in a Q_PROPERTY. The only difference with Q_PROPERTY would be the semicolon before the
828 * name.
829 * W_PROPERTY need to be put after all the setters, getters, signals and members have been declared.
830 *
831 * <type> can optionally be put in parentheses, if you have a type containing a comma
832 */
833#define W_PROPERTY(...) W_MACRO_MSVC_EXPAND(W_PROPERTY2(__VA_ARGS__)) // expands the READ, WRITE, and other sub marcos
834#define W_PROPERTY2(TYPE, NAME, ...) \
835 W_STATE_APPEND(w_PropertyState, \
836 w_internal::makeMetaPropertyInfo<W_MACRO_REMOVEPAREN(TYPE)>(\
837 #NAME, W_MACRO_STRIGNIFY(W_MACRO_REMOVEPAREN(TYPE)), __VA_ARGS__))
838
839#define WRITE , &W_ThisType::
840#define READ , &W_ThisType::
841#define NOTIFY , W_Notify, &W_ThisType::
842#define RESET , W_Reset, &W_ThisType::
843#define MEMBER , &W_ThisType::
844#define CONSTANT , W_Constant
845#define FINAL , W_Final
846
847#undef Q_PRIVATE_PROPERTY // the official macro is not a variadic macro, and the coma in READ would break it
848#define Q_PRIVATE_PROPERTY(...)
849
850/** W_ENUM(<name>, <values>)
851 * Similar to Q_ENUM, but one must also manually write all the values.
852 */
853#define W_ENUM(NAME, ...) \
854 W_STATE_APPEND(w_EnumState, w_internal::makeMetaEnumInfo<NAME,false>( \
855 #NAME, w_internal::enum_sequence<NAME,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \
856 Q_ENUM(NAME)
857
858
859/** W_ENUM_NS(<name>, <values>)
860 * Similar to Q_ENUM_NS, like W_ENUM
861 */
862#define W_ENUM_NS(NAME, ...) \
863 W_STATE_APPEND_NS(w_EnumState, w_internal::makeMetaEnumInfo<NAME,false>( \
864 #NAME, w_internal::enum_sequence<NAME,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \
865 Q_ENUM_NS(NAME)
866
867/** W_FLAG(<name>, <values>)
868 * Similar to Q_FLAG, but one must also manually write all the values.
869 */
870namespace w_internal {
871template<typename T> struct QEnumOrQFlags { using Type = T; };
872template<typename T> struct QEnumOrQFlags<QFlags<T>> { using Type = T; };
873}
874#define W_FLAG(NAME, ...) \
875 W_STATE_APPEND(w_EnumState, w_internal::makeMetaEnumInfo<w_internal::QEnumOrQFlags<NAME>::Type,true>( \
876 #NAME, w_internal::enum_sequence<w_internal::QEnumOrQFlags<NAME>::Type,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \
877 Q_FLAG(NAME)
878
879/** W_FLAG_NS(<name>, <values>)
880 * Similar to Q_FLAG_NS, like W_FLAG.
881 */
882#define W_FLAG_NS(NAME, ...) \
883 W_STATE_APPEND_NS(w_EnumState, w_internal::makeMetaEnumInfo<w_internal::QEnumOrQFlags<NAME>::Type,true>( \
884 #NAME, w_internal::enum_sequence<w_internal::QEnumOrQFlags<NAME>::Type,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \
885 Q_FLAG_NS(NAME)
886
887/** Same as Q_CLASSINFO. Note, Q_CLASSINFO_NS is required for namespace */
888#define W_CLASSINFO(A, B) \
889 W_STATE_APPEND(w_ClassInfoState, \
890 std::pair<w_internal::StaticString<sizeof(A)>, w_internal::StaticString<sizeof(B)>>{ {A}, {B} })
891
892/** Same as Q_CLASSINFO, but within a namespace */
893#define W_CLASSINFO_NS(A, B) \
894 W_STATE_APPEND_NS(w_ClassInfoState, \
895 std::pair<w_internal::StaticString<sizeof(A)>, w_internal::StaticString<sizeof(B)>>{ {A}, {B} })
896
897
898/** Same as Q_INTERFACE */
899#define W_INTERFACE(A) \
900 W_STATE_APPEND(w_InterfaceState, static_cast<A*>(nullptr))
901
902
903/** \macro W_REGISTER_ARGTYPE(TYPE)
904 Registers TYPE so it can be used as a parameter of a signal/slot or return value.
905 The normalized signature must be used.
906 Note: This does not imply Q_DECLARE_METATYPE, and Q_DECLARE_METATYPE does not imply this
907*/
908namespace w_internal { template<typename T> struct W_TypeRegistery { enum { registered = false }; }; }
909#define W_REGISTER_ARGTYPE(...) namespace w_internal { \
910 template<> struct W_TypeRegistery<__VA_ARGS__> { \
911 enum { registered = true }; \
912 static constexpr auto name = makeStaticString(#__VA_ARGS__); \
913 };}
914W_REGISTER_ARGTYPE(char*)
915W_REGISTER_ARGTYPE(const char*)
916
917#else // Q_MOC_RUN
918// just to avoid parse errors when moc is run over things that it should ignore
919#define W_SIGNAL(...) ;
920#define W_SIGNAL_COMPAT(...) ;
921#define W_PROPERTY(...)
922#define W_SLOT(...)
923#define W_CLASSINFO(...)
924#define W_INTERFACE(...)
925#define W_CONSTRUCTOR(...)
926#define W_FLAG(...)
927#define W_ENUM(...)
928#endif
929