1 /**************************************************************************** 2 ** 3 ** DQt - D bindings for the Qt Toolkit 4 ** 5 ** GNU Lesser General Public License Usage 6 ** This file may be used under the terms of the GNU Lesser 7 ** General Public License version 3 as published by the Free Software 8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 9 ** packaging of this file. Please review the following information to 10 ** ensure the GNU Lesser General Public License version 3 requirements 11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 12 ** 13 ****************************************************************************/ 14 module qt.core.objectdefs_impl; 15 extern(C++): 16 17 import qt.config; 18 import qt.core.atomic; 19 import qt.core.object; 20 import qt.helpers; 21 22 /+ #ifndef QOBJECTDEFS_H 23 #error Do not include qobjectdefs_impl.h directly 24 #endif 25 26 #if 0 27 #pragma qt_sync_skip_header_check 28 #pragma qt_sync_stop_processing 29 #endif 30 31 class QObject; +/ 32 33 extern(C++, "QtPrivate") { 34 /+ template <typename T> struct RemoveRef { typedef T Type; }; 35 template <typename T> struct RemoveRef<T&> { typedef T Type; }; 36 template <typename T> struct RemoveConstRef { typedef T Type; }; 37 template <typename T> struct RemoveConstRef<const T&> { typedef T Type; }; 38 39 /* 40 The following List classes are used to help to handle the list of arguments. 41 It follow the same principles as the lisp lists. 42 List_Left<L,N> take a list and a number as a parameter and returns (via the Value typedef, 43 the list composed of the first N element of the list 44 */ 45 // With variadic template, lists are represented using a variadic template argument instead of the lisp way 46 template <typename...> struct List {}; 47 template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; }; 48 template <typename, typename> struct List_Append; 49 template <typename... L1, typename...L2> struct List_Append<List<L1...>, List<L2...>> { typedef List<L1..., L2...> Value; }; 50 template <typename L, int N> struct List_Left { 51 typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value; 52 }; 53 template <typename L> struct List_Left<L, 0> { typedef List<> Value; }; 54 // List_Select<L,N> returns (via typedef Value) the Nth element of the list L 55 template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; }; 56 template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; }; 57 58 /* 59 trick to set the return value of a slot that works even if the signal or the slot returns void 60 to be used like function(), ApplyReturnValue<ReturnType>(&return_value) 61 if function() returns a value, the operator,(T, ApplyReturnValue<ReturnType>) is called, but if it 62 returns void, the builtin one is used without an error. 63 */ 64 template <typename T> 65 struct ApplyReturnValue { 66 void *data; 67 explicit ApplyReturnValue(void *data_) : data(data_) {} 68 }; 69 template<typename T, typename U> 70 void operator,(T &&value, const ApplyReturnValue<U> &container) { 71 if (container.data) 72 *reinterpret_cast<U *>(container.data) = std::forward<T>(value); 73 } +/ 74 /+void operator ,(T)(T, ref const(ApplyReturnValue!(void)) ) {}+/ 75 76 77 /* 78 The FunctionPointer<Func> struct is a type trait for function pointer. 79 - ArgumentCount is the number of argument, or -1 if it is unknown 80 - the Object typedef is the Object of a pointer to member function 81 - the Arguments typedef is the list of argument (in a QtPrivate::List) 82 - the Function typedef is an alias to the template parameter Func 83 - the call<Args, R>(f,o,args) method is used to call that slot 84 Args is the list of argument of the signal 85 R is the return type of the signal 86 f is the function pointer 87 o is the receiver object 88 and args is the array of pointer to arguments, as used in qt_metacall 89 90 The Functor<Func,N> struct is the helper to call a functor of N argument. 91 its call function is the same as the FunctionPointer::call function. 92 */ 93 /+ template<class T> using InvokeGenSeq = typename T::Type; 94 95 template<int...> struct IndexesList { using Type = IndexesList; }; 96 97 template<int N, class S1, class S2> struct ConcatSeqImpl; 98 99 template<int N, int... I1, int... I2> 100 struct ConcatSeqImpl<N, IndexesList<I1...>, IndexesList<I2...>> 101 : IndexesList<I1..., (N + I2)...>{}; 102 103 template<int N, class S1, class S2> 104 using ConcatSeq = InvokeGenSeq<ConcatSeqImpl<N, S1, S2>>; 105 106 template<int N> struct GenSeq; 107 template<int N> using makeIndexSequence = InvokeGenSeq<GenSeq<N>>; 108 109 template<int N> 110 struct GenSeq : ConcatSeq<N/2, makeIndexSequence<N/2>, makeIndexSequence<N - N/2>>{}; 111 112 template<> struct GenSeq<0> : IndexesList<>{}; 113 template<> struct GenSeq<1> : IndexesList<0>{}; 114 115 template<int N> 116 struct Indexes { using Value = makeIndexSequence<N>; }; 117 118 template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; }; 119 120 template <typename, typename, typename, typename> struct FunctorCall; 121 template <int... II, typename... SignalArgs, typename R, typename Function> 122 struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> { 123 static void call(Function &f, void **arg) { 124 f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); 125 } 126 }; 127 template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> 128 struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> { 129 static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) { 130 (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); 131 } 132 }; 133 template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> 134 struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> { 135 static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg) { 136 (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); 137 } 138 }; 139 #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 140 template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> 141 struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> { 142 static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg) { 143 (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); 144 } 145 }; 146 template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> 147 struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> { 148 static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg) { 149 (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); 150 } 151 }; 152 #endif 153 154 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)> 155 { 156 typedef Obj Object; 157 typedef List<Args...> Arguments; 158 typedef Ret ReturnType; 159 typedef Ret (Obj::*Function) (Args...); 160 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; 161 template <typename SignalArgs, typename R> 162 static void call(Function f, Obj *o, void **arg) { 163 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); 164 } 165 }; 166 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const> 167 { 168 typedef Obj Object; 169 typedef List<Args...> Arguments; 170 typedef Ret ReturnType; 171 typedef Ret (Obj::*Function) (Args...) const; 172 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; 173 template <typename SignalArgs, typename R> 174 static void call(Function f, Obj *o, void **arg) { 175 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); 176 } 177 }; 178 179 template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...)> 180 { 181 typedef List<Args...> Arguments; 182 typedef Ret ReturnType; 183 typedef Ret (*Function) (Args...); 184 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false}; 185 template <typename SignalArgs, typename R> 186 static void call(Function f, void *, void **arg) { 187 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg); 188 } 189 }; 190 191 #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 192 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) noexcept> 193 { 194 typedef Obj Object; 195 typedef List<Args...> Arguments; 196 typedef Ret ReturnType; 197 typedef Ret (Obj::*Function) (Args...) noexcept; 198 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; 199 template <typename SignalArgs, typename R> 200 static void call(Function f, Obj *o, void **arg) { 201 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); 202 } 203 }; 204 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const noexcept> 205 { 206 typedef Obj Object; 207 typedef List<Args...> Arguments; 208 typedef Ret ReturnType; 209 typedef Ret (Obj::*Function) (Args...) const noexcept; 210 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true}; 211 template <typename SignalArgs, typename R> 212 static void call(Function f, Obj *o, void **arg) { 213 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg); 214 } 215 }; 216 217 template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...) noexcept> 218 { 219 typedef List<Args...> Arguments; 220 typedef Ret ReturnType; 221 typedef Ret (*Function) (Args...) noexcept; 222 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false}; 223 template <typename SignalArgs, typename R> 224 static void call(Function f, void *, void **arg) { 225 FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg); 226 } 227 }; 228 #endif 229 230 template<typename Function, int N> struct Functor 231 { 232 template <typename SignalArgs, typename R> 233 static void call(Function &f, void *, void **arg) { 234 FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg); 235 } 236 }; 237 238 /* 239 Logic that checks if the underlying type of an enum is signed or not. 240 Needs an external, explicit check that E is indeed an enum. Works 241 around the fact that it's undefined behavior to instantiate 242 std::underlying_type on non-enums (cf. §20.13.7.6 [meta.trans.other]). 243 */ 244 template<typename E, typename Enable = void> 245 struct IsEnumUnderlyingTypeSigned : std::false_type 246 { 247 }; 248 249 template<typename E> 250 struct IsEnumUnderlyingTypeSigned<E, typename std::enable_if<std::is_enum<E>::value>::type> 251 : std::integral_constant<bool, std::is_signed<typename std::underlying_type<E>::type>::value> 252 { 253 }; 254 255 /* 256 Logic that checks if the argument of the slot does not narrow the 257 argument of the signal when used in list initialization. Cf. §8.5.4.7 258 [dcl.init.list] for the definition of narrowing. 259 For incomplete From/To types, there's no narrowing. 260 */ 261 template<typename From, typename To, typename Enable = void> 262 struct AreArgumentsNarrowedBase : std::false_type 263 { 264 }; 265 266 template <typename T> 267 using is_bool = std::is_same<bool, typename std::decay<T>::type>; 268 269 template<typename From, typename To> 270 struct AreArgumentsNarrowedBase<From, To, typename std::enable_if<sizeof(From) && sizeof(To)>::type> 271 : std::integral_constant<bool, 272 (std::is_floating_point<From>::value && std::is_integral<To>::value) || 273 (std::is_floating_point<From>::value && std::is_floating_point<To>::value && sizeof(From) > sizeof(To)) || 274 ((std::is_pointer<From>::value || std::is_member_pointer<From>::value) && QtPrivate::is_bool<To>::value) || 275 ((std::is_integral<From>::value || std::is_enum<From>::value) && std::is_floating_point<To>::value) || 276 (std::is_integral<From>::value && std::is_integral<To>::value 277 && (sizeof(From) > sizeof(To) 278 || (std::is_signed<From>::value ? !std::is_signed<To>::value 279 : (std::is_signed<To>::value && sizeof(From) == sizeof(To))))) || 280 (std::is_enum<From>::value && std::is_integral<To>::value 281 && (sizeof(From) > sizeof(To) 282 || (IsEnumUnderlyingTypeSigned<From>::value ? !std::is_signed<To>::value 283 : (std::is_signed<To>::value && sizeof(From) == sizeof(To))))) 284 > 285 { 286 }; 287 288 /* 289 Logic that check if the arguments of the slot matches the argument of the signal. 290 To be used like this: 291 Q_STATIC_ASSERT(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value) 292 */ 293 template<typename A1, typename A2> struct AreArgumentsCompatible { 294 static int test(const typename RemoveRef<A2>::Type&); 295 static char test(...); 296 static const typename RemoveRef<A1>::Type &dummy(); 297 enum { value = sizeof(test(dummy())) == sizeof(int) }; 298 #ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT 299 using AreArgumentsNarrowed = AreArgumentsNarrowedBase<typename RemoveRef<A1>::Type, typename RemoveRef<A2>::Type>; 300 Q_STATIC_ASSERT_X(!AreArgumentsNarrowed::value, "Signal and slot arguments are not compatible (narrowing)"); 301 #endif 302 }; 303 template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; }; 304 template<typename A> struct AreArgumentsCompatible<A&, A&> { enum { value = true }; }; 305 // void as a return value 306 template<typename A> struct AreArgumentsCompatible<void, A> { enum { value = true }; }; 307 template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; }; 308 template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; }; 309 310 template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; 311 template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; }; 312 template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; }; 313 template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2> 314 struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>> 315 { 316 enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value 317 && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value }; 318 }; 319 320 /* 321 Find the maximum number of arguments a functor object can take and be still compatible with 322 the arguments from the signal. 323 Value is the number of arguments, or -1 if nothing matches. 324 */ 325 template <typename Functor, typename ArgList> struct ComputeFunctorArgumentCount; 326 327 template <typename Functor, typename ArgList, bool Done> struct ComputeFunctorArgumentCountHelper 328 { enum { Value = -1 }; }; 329 template <typename Functor, typename First, typename... ArgList> 330 struct ComputeFunctorArgumentCountHelper<Functor, List<First, ArgList...>, false> 331 : ComputeFunctorArgumentCount<Functor, 332 typename List_Left<List<First, ArgList...>, sizeof...(ArgList)>::Value> {}; 333 334 template <typename Functor, typename... ArgList> struct ComputeFunctorArgumentCount<Functor, List<ArgList...>> 335 { 336 template <typename D> static D dummy(); 337 template <typename F> static auto test(F f) -> decltype(((f.operator()((dummy<ArgList>())...)), int())); 338 static char test(...); 339 enum { 340 Ok = sizeof(test(dummy<Functor>())) == sizeof(int), 341 Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value) 342 }; 343 }; 344 345 /* get the return type of a functor, given the signal argument list */ 346 template <typename Functor, typename ArgList> struct FunctorReturnType; 347 template <typename Functor, typename ... ArgList> struct FunctorReturnType<Functor, List<ArgList...>> { 348 template <typename D> static D dummy(); 349 typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value; 350 }; +/ 351 352 // internal base class (interface) containing functions required to call a slot managed by a pointer to function. 353 extern(C++, class) struct QSlotObjectBase { 354 private: 355 QAtomicInt m_ref; 356 // don't use virtual functions here; we don't want the 357 // compiler to create tons of per-polymorphic-class stuff that 358 // we'll never need. We just use one function pointer. 359 alias ImplFn = ExternCPPFunc!(void function(int which, QSlotObjectBase* this_, QObject receiver, void** args, bool* ret)); 360 const(ImplFn) m_impl; 361 protected: 362 enum Operation { 363 Destroy, 364 Call, 365 Compare, 366 367 NumOperations 368 } 369 public: 370 /+ explicit +/this(ImplFn fn) 371 { 372 this.m_ref = QAtomicInt(1); 373 this.m_impl = fn; 374 } 375 376 // pragma(inline, true) int ref_()/+ noexcept+/ { return m_ref.ref_(); } 377 /* pragma(inline, true) void destroyIfLastRef()/+ noexcept+/ 378 { if (!m_ref.deref()) m_impl(Operation.Destroy, &this, null, null, null); } 379 */ 380 pragma(inline, true) bool compare(void** a) { bool ret = false; m_impl(Operation.Compare, &this, null, a, &ret); return ret; } 381 /+ inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, nullptr); } +/ 382 protected: 383 ~this() {} 384 private: 385 /+ Q_DISABLE_COPY_MOVE(QSlotObjectBase) +/ 386 @disable this(this); 387 /+this(ref const(QSlotObjectBase));+//+ref QSlotObjectBase operator =(ref const(QSlotObjectBase));+/ } 388 389 // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject 390 // Args and R are the List of arguments and the return type of the signal to which the slot is connected. 391 /+ template<typename Func, typename Args, typename R> class QSlotObject : public QSlotObjectBase 392 { 393 typedef QtPrivate::FunctionPointer<Func> FuncType; 394 Func function; 395 static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) 396 { 397 switch (which) { 398 case Destroy: 399 delete static_cast<QSlotObject*>(this_); 400 break; 401 case Call: 402 FuncType::template call<Args, R>(static_cast<QSlotObject*>(this_)->function, static_cast<typename FuncType::Object *>(r), a); 403 break; 404 case Compare: 405 *ret = *reinterpret_cast<Func *>(a) == static_cast<QSlotObject*>(this_)->function; 406 break; 407 case NumOperations: ; 408 } 409 } 410 public: 411 explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {} 412 }; 413 // implementation of QSlotObjectBase for which the slot is a functor (or lambda) 414 // N is the number of arguments 415 // Args and R are the List of arguments and the return type of the signal to which the slot is connected. 416 template<typename Func, int N, typename Args, typename R> class QFunctorSlotObject : public QSlotObjectBase 417 { 418 typedef QtPrivate::Functor<Func, N> FuncType; 419 Func function; 420 static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) 421 { 422 switch (which) { 423 case Destroy: 424 delete static_cast<QFunctorSlotObject*>(this_); 425 break; 426 case Call: 427 FuncType::template call<Args, R>(static_cast<QFunctorSlotObject*>(this_)->function, r, a); 428 break; 429 case Compare: // not implemented 430 case NumOperations: 431 Q_UNUSED(ret); 432 } 433 } 434 public: 435 explicit QFunctorSlotObject(Func f) : QSlotObjectBase(&impl), function(std::move(f)) {} 436 }; 437 438 // typedefs for readability for when there are no parameters 439 template <typename Func> 440 using QSlotObjectWithNoArgs = QSlotObject<Func, 441 QtPrivate::List<>, 442 typename QtPrivate::FunctionPointer<Func>::ReturnType>; 443 444 template <typename Func, typename R> 445 using QFunctorSlotObjectWithNoArgs = QFunctorSlotObject<Func, 0, QtPrivate::List<>, R>; 446 447 template <typename Func> 448 using QFunctorSlotObjectWithNoArgsImplicitReturn = QFunctorSlotObjectWithNoArgs<Func, typename QtPrivate::FunctionPointer<Func>::ReturnType>; +/ 449 } 450 451 extern(D) struct DQtStaticSlotObject(Params...) 452 { 453 QSlotObjectBase base; 454 alias Dg = void delegate(Params); 455 Dg dg; 456 457 extern(C++) static void impl(int which, QSlotObjectBase *this_, QObject r, void **a, bool *ret) 458 { 459 import core.stdcpp.new_; 460 switch (which) { 461 case QSlotObjectBase.Operation.Destroy: 462 cpp_delete(cast(DQtStaticSlotObject*)(this_)); 463 break; 464 case QSlotObjectBase.Operation.Call: 465 (cast(DQtStaticSlotObject*)(this_)).dg(); 466 break; 467 case QSlotObjectBase.Operation.Compare: // not implemented 468 case QSlotObjectBase.Operation.NumOperations: 469 //Q_UNUSED(ret); 470 default: 471 } 472 } 473 public: 474 this(Dg dg) 475 { 476 base = QSlotObjectBase(&impl); 477 this.dg = dg; 478 } 479 } 480 481 extern(D) struct DQtMemberSlotObject(T, alias F, Params...) if(is(T: QObject)) 482 { 483 QSlotObjectBase base; 484 485 /* Need to use a custom mangling, because the template parameters 486 * may not have a C++ mangling. */ 487 pragma(mangle, DQtMemberSlotObject.mangleof ~ "__impl") 488 extern(C++) static void impl(int which, QSlotObjectBase *this_, QObject r, void **a, bool *ret) 489 { 490 import core.stdcpp.new_; 491 import std.traits; 492 switch (which) { 493 case QSlotObjectBase.Operation.Destroy: 494 cpp_delete(cast(DQtMemberSlotObject*)(this_)); 495 break; 496 case QSlotObjectBase.Operation.Call: 497 mixin("extern(" ~ functionLinkage!F ~ ") ReturnType!F delegate(Parameters!F) dg;"); 498 dg.ptr = cast(void*)r; 499 dg.funcptr = &F; 500 mixin((){ 501 import std.conv; 502 string r; 503 r = "dg("; 504 foreach(i; 0..Params.length) 505 { 506 r ~= text("*cast(Params[", i, "]*)a[", i + 1, "], "); 507 } 508 r ~= ");"; 509 return r; 510 }()); 511 break; 512 case QSlotObjectBase.Operation.Compare: // not implemented 513 case QSlotObjectBase.Operation.NumOperations: 514 //Q_UNUSED(ret); 515 default: 516 } 517 } 518 public: 519 @disable this(); 520 this(int dummy) 521 { 522 base = QSlotObjectBase(&impl); 523 } 524 }