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
33namespace w_internal {
34using 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
39template<size_t... I1, size_t... I2>
40index_sequence<I1... , (I2 +(sizeof...(I1)))...>
41make_index_sequence_helper_merge(index_sequence<I1...>, index_sequence<I2...>);
42
43template<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};
48template<> struct make_index_sequence_helper<1> { using result = index_sequence<0>; };
49template<> struct make_index_sequence_helper<0> { using result = index_sequence<>; };
50template<std::size_t N> using make_index_sequence = typename make_index_sequence_helper<N>::result;
51#else
52using std::make_index_sequence;
53#endif
54
55/// integral_constant with an inheritance based fallback
56struct IndexBase {};
57template <size_t> struct Index : IndexBase {};
58template <size_t I> constexpr auto index = Index<I>{};
59
60template<typename... Args> constexpr void ordered(Args...) {}
61template<class T> constexpr void ordered2(std::initializer_list<T>) {}
62
63/// Compute the sum of many integers
64template<typename... Args>
65constexpr 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 )
75template <int ...args>
76constexpr int summed = sums(args...);
77
78/// constexpr friendly string_view
79struct 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
88template<size_t N>
89constexpr 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
94template<size_t N = 0>
95struct StringViewArray {
96 StringView data[(N > 0 ? N : 1)]{};
97
98 constexpr auto operator[] (size_t i) const { return data[i]; }
99};
100
101template<size_t... Ns>
102constexpr 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}
112template<size_t R, size_t... Ns, size_t... Ts, size_t... Is, class... Args>
113constexpr 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}
124template<size_t... Ts, size_t... Ns>
125constexpr 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
131template<size_t R, size_t... Ns, size_t... Is, class... Args>
132constexpr 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}
142template<size_t... Ns>
143constexpr 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
152enum 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};
175constexpr uint operator|(uint a, PropertyFlags b) { return a | uint(b); }
176
177template <int N> struct W_MethodFlags { static constexpr int value = N; };
178constexpr 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
185namespace 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
197namespace 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
215constexpr w_internal::W_MethodFlags<0x10> W_Compat{};
216constexpr w_internal::W_MethodFlags<0x40> W_Scriptable{};
217constexpr struct {} W_Notify{};
218constexpr struct {} W_Reset{};
219constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Constant)> W_Constant{};
220constexpr std::integral_constant<int, int(w_internal::PropertyFlags::Final)> W_Final{};
221
222namespace w_internal {
223
224/// Holds information about a method
225template<typename F, int Flags, typename IC, typename ParamTypes, typename ParamNames = StringViewArray<>>
226struct 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
238template<typename F, typename ParamTypes, int... Flags, typename IntegralConstant>
239constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Slot.value, IntegralConstant, ParamTypes>
240makeMetaSlotInfo(F f, StringView name, IntegralConstant, const ParamTypes &paramTypes, W_MethodFlags<Flags>...)
241{ return { f, name, paramTypes, {} }; }
242
243// Called from the W_METHOD macro
244template<typename F, typename ParamTypes, int... Flags, typename IntegralConstant>
245constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Method.value, IntegralConstant, ParamTypes>
246makeMetaMethodInfo(F f, StringView name, IntegralConstant, const ParamTypes &paramTypes, W_MethodFlags<Flags>...)
247{ return { f, name, paramTypes, {} }; }
248
249// Called from the W_SIGNAL macro
250template<typename F, typename ParamTypes, typename ParamNames, int... Flags, typename IntegralConstant>
251constexpr MetaMethodInfo<F, summed<Flags...> | W_MethodType::Signal.value, IntegralConstant,
252 ParamTypes, ParamNames>
253makeMetaSignalInfo(F f, StringView name, IntegralConstant, const ParamTypes &paramTypes,
254 const ParamNames &paramNames, W_MethodFlags<Flags>...)
255{ return { f, name, paramTypes, paramNames }; }
256
257/// Holds information about a constructor
258template<typename... Args>
259struct 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
267template<typename... Args>
268constexpr MetaConstructorInfo<Args...> makeMetaConstructorInfo(StringView name)
269{ return { name }; }
270
271struct Empty{
272 constexpr operator bool() const { return false; }
273};
274
275/// Holds information about a property
276template<typename Type, typename Getter = Empty, typename Setter = Empty,
277 typename Member = Empty, typename Notify = Empty, typename Reset = Empty, int Flags = 0>
278struct 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
323template <typename PropInfo> constexpr auto parseProperty(const PropInfo &p) { return p; }
324// setter
325template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail>
326constexpr 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
329template <typename PropInfo, typename Obj, typename Arg, typename Ret, typename... Tail>
330constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg) noexcept, Tail... t)
331{ return parseProperty(p.setSetter(s) , t...); }
332#endif
333// getter
334template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
335constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(), Tail... t)
336{ return parseProperty(p.setGetter(s), t...); }
337template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
338constexpr 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
341template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
342constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() noexcept, Tail... t)
343{ return parseProperty(p.setGetter(s), t...); }
344template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
345constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const noexcept, Tail... t)
346{ return parseProperty(p.setGetter(s), t...); }
347#endif
348// member
349template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
350constexpr auto parseProperty(const PropInfo &p, Ret Obj::*s, Tail... t)
351{ return parseProperty(p.setMember(s) ,t...); }
352// notify
353template <typename PropInfo, typename F, typename... Tail>
354constexpr auto parseProperty(const PropInfo &p, decltype(W_Notify), F f, Tail... t)
355{ return parseProperty(p.setNotify(f) ,t...); }
356// reset
357template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
358constexpr 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
361template <typename PropInfo, typename Obj, typename Ret, typename... Tail>
362constexpr 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
366template <typename PropInfo, int Flag, typename... Tail>
367constexpr auto parseProperty(const PropInfo &p, std::integral_constant<int, Flag>, Tail... t)
368{ return parseProperty(p.template addFlag<Flag>() ,t...); }
369
370template<typename T, typename ... Args>
371constexpr auto makeMetaPropertyInfo(StringView name, StringView type, Args... args) {
372 auto meta = MetaPropertyInfo<T>{ name, type, {}, {}, {}, {}, {} };
373 return parseProperty(meta, args...);
374}
375
376template <typename T, typename = void> struct EnumIsScoped {
377 enum { Value = std::is_convertible<T, int>::value ? 0 : 2 };
378};
379template <typename T> struct EnumIsScoped<QFlags<T>, void> : EnumIsScoped<typename QFlags<T>::enum_type> {};
380
381template<typename T> struct QEnumOrQFlags { using Type = T; };
382template<typename T> struct QEnumOrQFlags<QFlags<T>> { using Type = T; };
383
384/// Holds information about an enum
385template<bool HasAlias, typename Values_, typename Names, int Flags>
386struct 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};
396template<typename Enum, Enum... Value> struct enum_sequence {};
397// called from W_ENUM and W_FLAG
398template<typename Enum, int Flag, Enum... Values, typename Names>
399constexpr 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}
403template<typename Enum, int Flag, Enum... Values, typename Names>
404constexpr 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)
410template<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 ...
431template<typename Func, int Idx> struct SignalImplementation {};
432template<typename Obj, typename Ret, typename... Args, int Idx>
433struct 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};
442template<typename Obj, typename... Args, int Idx>
443struct 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};
450template<typename Obj, typename Ret, typename... Args, int Idx>
451struct 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};
460template<typename Obj, typename... Args, int Idx>
461struct 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.
476template<typename T> T &getParentObjectHelper(void* (T::*)(const char*));
477
478// helper class that can access the private member of any class with W_OBJECT
479struct FriendHelper;
480
481inline 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.
484template <typename... Args>
485struct QNonConstOverload
486{
487 template <typename R, typename T>
488 constexpr auto operator()(R (T::*ptr)(Args...)) const
489 { return ptr; }
490};
491template <typename... Args>
492struct QConstOverload
493{
494 template <typename R, typename T>
495 constexpr auto operator()(R (T::*ptr)(Args...) const) const
496 { return ptr; }
497};
498template <typename... Args>
499struct 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};
508template <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
592namespace w_internal {
593constexpr 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
602namespace 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
607template<class State, class TPP>
608void w_state(IndexBase, State, TPP);
609
610#if __cplusplus > 201700L
611template<size_t L, class State, class TPP, size_t N , size_t M, size_t X = (N+M)/2>
612constexpr 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}
624template<size_t L, class State, class TPP, size_t N = 1>
625constexpr 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
635template<size_t L, class State, class TPP>
636constexpr auto stateCount = count<L, State, TPP>();
637#else
638template<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>
642struct CountBetween;
643
644template<size_t L, class State, class TPP, size_t N, size_t M, size_t X>
645struct CountBetween<L, State, TPP, N, M, X, true, true> {
646 static constexpr auto value = N;
647};
648template<size_t L, class State, class TPP, size_t N, size_t M, size_t X>
649struct CountBetween<L, State, TPP, N, M, X, false, true> {
650 static constexpr auto value = M;
651};
652template<size_t L, class State, class TPP, size_t N, size_t M, size_t X>
653struct CountBetween<L, State, TPP, N, M, X, true, false> {
654 static constexpr auto value = CountBetween<L, State, TPP, N, X>::value;
655};
656template<size_t L, class State, class TPP, size_t N, size_t M, size_t X>
657struct CountBetween<L, State, TPP, N, M, X, false, false> {
658 static constexpr auto value = CountBetween<L, State, TPP, X, M>::value;
659};
660
661template<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>
664struct Count;
665
666template<size_t L, class State, class TPP, size_t N>
667struct Count<L, State, TPP, N, true> {
668 static constexpr auto value = CountBetween<L, State, TPP, N/2, N>::value;
669};
670template<size_t L, class State, class TPP, size_t N>
671struct Count<L, State, TPP, N, false> {
672 static constexpr auto value = Count<L, State, TPP, N*2>::value;
673};
674
675template<size_t L, class State, class TPP>
676constexpr auto stateCount = Count<L, State, TPP>::value;
677#endif
678
679struct SlotStateTag {};
680struct SignalStateTag {};
681struct MethodStateTag {};
682struct ConstructorStateTag {};
683struct PropertyStateTag {};
684struct EnumStateTag {};
685struct ClassInfoStateTag {};
686struct 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
911namespace 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 };}
917W_REGISTER_ARGTYPE(char*)
918W_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