翻蚳è ããïŒããã¯ãQt 5ã®ä¿¡å·ãšã¹ãããã®å éšã¢ãŒããã¯ãã£ã«é¢ããOlivier Goffartã«ããèšäºã®ç¿»èš³ã®ç¬¬2éšã§ã ã第1éšã®ç¿»èš³ã¯ãã¡ãã§ãã
Qt5ã®æ°ããæ§æ
æ°ããæ§æã¯æ¬¡ã®ããã«ãªããŸãã
QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
ãã®æçš¿ã§ã¯ãæ°ããæ§æã®å©ç¹ã«ã€ããŠæ¢ã«èª¬æããŸããã ã€ãŸããæ°ããæ§æã§ã¯ãã³ã³ãã€ã«æã«ä¿¡å·ãšã¹ãããããã§ãã¯ã§ããŸãã åŒæ°ããŸã£ããåãã¿ã€ãã§ãªãå ŽåãåŒæ°ãèªåçã«å€æããããšãã§ããŸãã ãŸããããŒãã¹ãšããŠããã®æ§æã䜿çšãããšãã©ã ãåŒã䜿çšã§ããŸãã
æ°ãããªãŒããŒããŒãã¡ãœãã
ãããæ©èœããããã«å¿ èŠãªå€æŽã¯ãããã§ããã äž»ãªã¢ã€ãã¢ã¯ãæ°ããQObject ::æ¥ç¶ãªãŒããŒããŒãã§ããããã¯ãchar *ã§ã¯ãªãé¢æ°ãã€ã³ã¿ãŒãåŒæ°ãšããŠåãåããŸãã ãããã¯3ã€ã®æ°ããã¡ãœããïŒæ¬äŒŒã³ãŒãïŒã§ãã
QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType type); QObject::connect(const QObject *sender, PointerToMemberFunction signal, PointerToFunction method) QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor method)
æåã®æ¹æ³ã¯ãå€ãæ§æã«æãè¿ãæ¹æ³ã§ããéä¿¡åŽã®ä¿¡å·ãåä¿¡åŽã®ã¹ãããã«æ¥ç¶ããŸãã ä»ã®2ã€ã¯ãã®æ¥ç¶ããªãŒããŒããŒãããéçé¢æ°ãšã¬ã·ãŒããŒãªãã®ãã¡ã³ã¯ã¿ãŒãä¿¡å·ã«æ¥ç¶ããŸãã ãã¹ãŠã®æ¹æ³ã¯éåžžã«äŒŒãŠããããã®æçš¿ã§ã¯æåã®æ¹æ³ã®ã¿ãåæããŸãã
ã¡ã³ããŒé¢æ°ãã€ã³ã¿ãŒ
説æãç¶ããåã«ãã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã«ã€ããŠå°ãã話ãããããšæããŸãã 以äžã¯ãé¢æ°ãžã®ãã€ã³ã¿ãŒã宣èšããŠåŒã³åºãéåžžã«ç°¡åãªã³ãŒãã§ãã
// myFunctionPtr - // void int void (QPoint::*myFunctionPtr)(int); myFunctionPtr = &QPoint::setX; QPoint p; QPoint *pp = &p; (p.*myFunctionPtr)(5); // p.setX(5); (pp->*myFunctionPtr)(5); // pp->setX(5);
ã¡ã³ããŒãã€ã³ã¿ãŒãšã¡ã³ããŒé¢æ°ãã€ã³ã¿ãŒã¯ãC ++ãµãã»ããã®äžè¬çãªéšåã§ãããããŸãäžè¬çã«äœ¿çšãããŠããªããããããŸãç¥ãããŠããŸããã è¯ããã¥ãŒã¹ã¯ãQtãšãã®æ°ããæ§æã䜿çšããããã«ããã«ã€ããŠç¥ãå¿ èŠããªãããšã§ãã èŠããŠããå¿ èŠãããã®ã¯ãæ¥ç¶ã®ä¿¡å·åã®åãšåã«é 眮ããå¿ èŠããããã®ã ãã§ãã éæ³ã®æŒç®å:: * ,. *ãŸãã¯-> *ãæ±ãå¿ èŠã¯ãããŸããã ãããã®éæ³ã®æŒç®åã䜿çšãããšãã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã宣èšããŠã¢ã¯ã»ã¹ã§ããŸãã ãã®ãããªãã€ã³ã¿ãŒã®åã«ã¯ãæ»ãå€ã®åãé¢æ°ãå±ããã¯ã©ã¹ããã¹ãŠã®åŒæ°ã®åãããã³é¢æ°ã®constæå®åãå«ãŸããŸãã
ã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã¯ãsizeofãç°ãªããããç¹ã«voidã«å€æããããšã¯ã§ããŸããã é¢æ°ã®ã·ã°ããã£ããããã«ç°ãªãå Žåãããé¢æ°ããå¥ã®é¢æ°ã«å€æããããšã¯ã§ããŸããã ããšãã°ã voidïŒMyClass :: *ïŒïŒintïŒconstããvoidïŒMyClass :: *ïŒïŒintïŒãžã®å€æãèš±å¯ãããŠããŸããïŒreinterpret_castã§ãããè¡ãããšãã§ããŸãããæšæºã«åŸã£ãŠãæªå®çŸ©ã®åäœïŒæªå®çŸ©ã®åäœïŒ ïŒé¢æ°ãåŒã³åºãããšããå ŽåïŒã
ã¡ã³ããŒé¢æ°ãã€ã³ã¿ãŒã¯ãéåžžã®é¢æ°ãã€ã³ã¿ãŒã ãã§ã¯ãããŸããã éåžžã®é¢æ°ãã€ã³ã¿ãŒã¯ãåã«æ©èœã³ãŒããé 眮ãããŠããã¢ãã¬ã¹ãžã®ãã€ã³ã¿ãŒã§ãã ãã ããã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã«ã¯ãããå€ãã®æ å ±ãä¿åããå¿ èŠããããŸããå€éç¶æ¿ã®å Žåãã¡ã³ããŒé¢æ°ã¯ä»®æ³ã§ãããé衚瀺ã®å Žåã¯ãªãã»ãããæã€ããšãã§ããŸãã ã¡ã³ããŒé¢æ°ãã€ã³ã¿ãŒã®sizeofã¯ãã¯ã©ã¹ã«å¿ããŠç°ãªãå ŽåããããŸã ã ãã®ãããããããæäœããããã®ç¹å¥ãªã±ãŒã¹ãå¿ èŠã§ãã
åç¹æ§ã¯ã©ã¹ïŒQtPrivate :: FunctionPointer
ã¿ã€ãQtPrivate :: FunctionPointerã®ããããã£ã®ã¯ã©ã¹ã玹ä»ããŸãã ããããã£ã¯ã©ã¹ã¯åºæ¬çã«ããã®åã«é¢ããã¡ã¿ããŒã¿ãè¿ããã«ããŒã¯ã©ã¹ã§ãã Qtã®ããããã£ã¯ã©ã¹ã®å¥ã®äŸã¯QTypeInfoã§ãã æ°ããæ§æã®å®è£ ã®ãã¬ãŒã ã¯ãŒã¯ã§ç¥ãå¿ èŠãããã®ã¯ãé¢æ°ãžã®ãã€ã³ã¿ã«é¢ããæ å ±ã§ãã template <typename T> struct FunctionPointerã¯ãã¡ã³ããŒãéããŠTã«é¢ããæ å ±ãæäŸããŸãã
- ArgumentCount-é¢æ°ã®åŒæ°ã®æ°ãè¡šãæ°å€
- ãªããžã§ã¯ã-ååšããŸããã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã«å¯ŸããŠã®ã¿ãã¯ã©ã¹ã®typedefã§ããããã®ã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒã§ãã
- åŒæ°-åŒæ°ã®ãªã¹ããã¡ã¿ããã°ã©ãã³ã°ãªã¹ãã®typedefãè¡šããŸã
- callïŒTïŒfunctionãQObject * receiverãvoid ** argsïŒ-æž¡ããããã©ã¡ãŒã¿ãŒã§é¢æ°ãåŒã³åºãéçé¢æ°
Qtã¯åŒãç¶ãC ++ 98ã³ã³ãã€ã©ããµããŒãããŠããŸããã€ãŸããæ®å¿µãªãããå¯å€æ°ã®åŒæ°ãæã€ãã³ãã¬ãŒãïŒvariadicãã³ãã¬ãŒãïŒã®ãµããŒããèŠæ±ããããšã¯ã§ããŸããã èšãæãããšãåŒæ°ã®æ°ããšã«ããããã£ã®ã¯ã©ã¹çšã«é¢æ°ãç¹æ®åããå¿ èŠããããŸãã 4ã€ã®ã¿ã€ãã®ç¹æ®åããããŸãïŒé¢æ°ãžã®éåžžã®ãã€ã³ã¿ãŒãã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒãå®æ°ã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒãããã³ãã¡ã³ã¯ã¿ãŒã ã¿ã€ãããšã«ãåŒæ°ã®æ°ããšã«ç¹æ®åãå¿ èŠã§ãã æ倧6ã€ã®åŒæ°ããµããŒãããŠããŸãã ã³ã³ãã€ã©ãå¯å€æ°ã®åŒæ°ãæã€ãã³ãã¬ãŒãããµããŒãããŠããå Žåãä»»æã®æ°ã®åŒæ°ã«å¯ŸããŠãå¯å€æ°ã®åŒæ°ãæã€ãã³ãã¬ãŒãã䜿çšããç¹æ®åããããŸãã FunctionPointerã®å®è£ ã¯qobjectdefs_impl.hã«ãããŸãã
QObject ::æ¥ç¶
å®è£ ã¯å®åã³ãŒãã®å€ãã«äŸåããŸãã ããã«ã€ããŠã¯èª¬æããŸããã qobject.hããã®æåã®æ°ãããªãŒããŒããŒãã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
template <typename Func1, typename Func2> static inline QMetaObject::Connection connect( const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { typedef QtPrivate::FunctionPointer<Func1> SignalType; typedef QtPrivate::FunctionPointer<Func2> SlotType; // , Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), ""The slot requires more arguments than the signal provides.""); Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value), ""Signal and slot arguments are not compatible.""); Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value), ""Return type of the slot is not compatible with the return type of the signal.""); const int *types; /* ... , QueuedConnection ...*/ QtPrivate::QSlotObjectBase *slotObj = new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, typename SignalType::ReturnType>(slot); return connectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot), slotObj, type, types, &SignalType::Object::staticMetaObject); }
ããã¥ã¡ã³ãã«ç€ºãããŠããããã«ãéä¿¡è ãšåä¿¡è ã¯QObject *ã ãã§ã¯ãªãããšã«ãé¢æ°ã®çœ²åã§æ°ä»ããŸããã ãããã¯ãå®éã«ã¯typename FunctionPointer :: Objectãžã®ãã€ã³ã¿ãŒã§ãã ã¡ã³ãé¢æ°ãžã®ãã€ã³ã¿ã®ã¿ã«å«ãŸãããªãŒããŒããŒããäœæããã«ã¯ã SFINAEã䜿çšããŸãã ãã㯠ã ObjectPoint㯠ãåãã¡ã³ãé¢æ°ãžã®ãã€ã³ã¿ã§ããå Žåã«ã®ã¿FunctionPointerã«ååšããããã§ãã
次ã«ãQ_STATIC_ASSERTã®æããå§ããŸãã ãŠãŒã¶ãŒãééããå Žåãæå³ã®ããã³ã³ãã€ã«ãšã©ãŒãçæããå¿ èŠããããŸãã ãŠãŒã¶ãŒãäœãééã£ãããšãããå Žåã¯ã_impl.hãã¡ã€ã«ã®ãã³ãã¬ãŒãã³ãŒãããŒãã«ã§ã¯ãªããããã§ãšã©ãŒã確èªããããšãéèŠã§ãã ãŠãŒã¶ãŒãå¿é ããªãããã«ãå éšå®è£ ãé衚瀺ã«ããå¿ èŠããããŸãã ããã¯ãå®è£ ã®è©³çŽ°ã«ç解ã§ããªããšã©ãŒã衚瀺ãããå Žåãå ±åããå¿ èŠããããšã©ãŒãšèŠãªãããããšãæå³ããŸãã
次ã«ãQSlotObjectã®ã€ã³ã¹ã¿ã³ã¹ãäœæããconnectImplïŒïŒã«æž¡ããŸãã QSlotObjectã¯ãã¹ãããã®åŒã³åºãã«åœ¹ç«ã€ã©ãããŒã§ãã 圌女ã¯ãŸããä¿¡å·åŒæ°ã®ã¿ã€ããç¥ã£ãŠãããé©åãªã¿ã€ãå€æãè¡ãããšãã§ããŸãã List_Leftã䜿çšããã®ã¯ãã¹ããããšåãæ°ã®åŒæ°ã®ã¿ãæž¡ãããã§ããããã«ãããä¿¡å·ãããåŒæ°ã®å°ãªãã¹ãããã«ä¿¡å·ãæ¥ç¶ã§ããŸãã
QObject :: connectImplã¯ãæ¥ç¶ãå®è¡ãããã©ã€ããŒãå éšé¢æ°ã§ãã QObjectPrivate :: Connectionæ§é äœã«ã¡ãœããã€ã³ããã¯ã¹ãä¿åãã代ããã«ãQSlotObjectBaseãžã®ãã€ã³ã¿ãŒãä¿åãããšããéãã¯ãããŸãããå ã®æ§æã«äŒŒãŠããŸãã
void **ãšããŠæž¡ããŠã¹ãããããçç±ã¯ãã¿ã€ããQt :: UniqueConnectionã®å Žåã«æ¯èŒã§ããããã«ããããã§ãã ãŸããvoid **ãšããŠæž¡ããŸãã ããã¯ãã¡ã³ããŒé¢æ°ãžã®ãã€ã³ã¿ãŒãžã®ãã€ã³ã¿ãŒã§ãã
ã·ã°ãã«ã€ã³ããã¯ã¹
ã·ã°ãã«ãã€ã³ã¿ãŒãšã·ã°ãã«ã€ã³ããã¯ã¹ãæ¥ç¶ããå¿ èŠããããŸãã ããã«ã¯MOCã䜿çšããŸãã ã¯ããããã¯ããã®æ°ããæ§æããŸã MOCã䜿çšããŠããããããåãé€ãèšç»ããªãããšãæå³ããŸã:-)ã MOCã¯qt_static_metacallã§ã³ãŒããçæãããã©ã¡ãŒã¿ãŒãæ¯èŒããŠæ£ããã€ã³ããã¯ã¹ãè¿ããŸãã connectImplã¯ãé¢æ°ãã€ã³ã¿ãŒãžã®ãã€ã³ã¿ãŒã§qt_static_metacallé¢æ°ãåŒã³åºããŸãã
void Counter::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { if (_c == QMetaObject::InvokeMetaMethod) { /* .... ....*/ } else if (_c == QMetaObject::IndexOfMethod) { int *result = reinterpret_cast<int *>(_a[0]); void **func = reinterpret_cast<void **>(_a[1]); { typedef void (Counter::*_t)(int ); if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&Counter::valueChanged)) { *result = 0; } } { typedef QString (Counter::*_t)(const QString & ); if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&Counter::someOtherSignal)) { *result = 1; } } { typedef void (Counter::*_t)(); if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&Counter::anotherSignal)) { *result = 2; } } } }
ã·ã°ãã«ã€ã³ããã¯ã¹ãã§ããã®ã§ãåã®æ§æãšåæ§ã®æ§æã䜿çšã§ããŸãã
QSlotObjectBase
QSlotObjectBaseã¯ãã¹ããããåæ ããconnectImplã«æž¡ããããªããžã§ã¯ãã§ãã çŸåšã®ã³ãŒãã衚瀺ããåã«ãQObject :: QSlotObjectBaseã瀺ããŸããããã¯Qt5ã¢ã«ãã¡çã§ããïŒ
struct QSlotObjectBase { QAtomicInt ref; QSlotObjectBase() : ref(1) {} virtual ~QSlotObjectBase(); virtual void call(QObject *receiver, void **a) = 0; virtual bool compare(void **) { return false; } };
ããã¯åºæ¬çã«ãé¢æ°ãã€ã³ã¿ãŒã®åŒã³åºããšæ¯èŒãå®è£ ãããã³ãã¬ãŒãã¯ã©ã¹ãä»ããŠåå®è£ ãããããã«èšèšãããã€ã³ã¿ãŒãã§ã€ã¹ã§ãã ããã¯ããã³ãã¬ãŒãã¯ã©ã¹QSlotObjectãQStaticSlotObjectããŸãã¯QFunctorSlotObjectã®ããããã«ãã£ãŠå®è£ ãããŸãã
åœã®ä»®æ³ããŒãã«
åé¡ã¯ããã®ãããªãªããžã§ã¯ããã€ã³ã¹ã¿ã³ã¹åãããã³ã«ãä»®æ³é¢æ°ãžã®ãã€ã³ã¿ã ãã§ãªãã RTTIãªã©ã®å¿ èŠã®ãªãå€ãã®æ å ±ãå«ãä»®æ³ããŒãã«ãäœæããå¿ èŠãããããšã§ãã ããã¯ã倧éã®åé·ããŒã¿ãšãã€ããªãã¡ã€ã«ã®æ¥å¢ã«ã€ãªãããŸãã ãããåé¿ããããã«ãQSlotObjectBaseã¯ããªã¢ãŒãã£ãã¯ã¯ã©ã¹ã§ã¯ãªãããã«å€æŽãããŸããã ä»®æ³æ©èœã¯æåã§ãšãã¥ã¬ãŒããããŸãã
class QSlotObjectBase { QAtomicInt m_ref; typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret); const ImplFn m_impl; protected: enum Operation { Destroy, Call, Compare }; public: explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {} inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); } inline void destroyIfLastRef() Q_DECL_NOTHROW { if (!m_ref.deref()) m_impl(Destroy, this, 0, 0, 0); } inline bool compare(void **a) { bool ret; m_impl(Compare, this, 0, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, 0); } };
m_implã¯ã以åã®ä»®æ³é¢æ°ã§ãã£ã3ã€ã®æäœãå®è¡ããéåžžã®é¢æ°ãã€ã³ã¿ãŒã§ãã ç¹°ãè¿ãå®è£ ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã§æ©èœããããã«èšå®ãããŸãã
ããªãã¯ãããè¯ãããšãèªãã ã®ã§ãããªãã®ã³ãŒãã«æ»ã£ãŠãã®æ¹æ³ã§ãã¹ãŠã®ä»®æ³é¢æ°ãå€æŽããå¿ èŠã¯ãããŸããã ã»ãšãã©ãã¹ãŠã®æ¥ç¶åŒã³åºããæ°ããç°ãªãã¿ã€ããçæãããããããã¯ãã®å Žåã«ã®ã¿è¡ãããŸãïŒQSsignObjectããéå§ããã·ã°ãã«ã·ã°ããã£ãšã¹ãããã«äŸåãããã³ãã¬ãŒããã©ã¡ãŒã¿ããããŸãïŒã
ä¿è·ããããéãããéããä¿¡å·
ã·ã°ãã«ã¯Qt4以åã§ä¿è·ãããŠããŸããã ãªããžã§ã¯ãã®ç¶æ ãå€åãããšãã«ä¿¡å·ããªããžã§ã¯ãããéä¿¡ããããã«èšèšããããšãéžæããŸããã ãããã¯ãªããžã§ã¯ãã®å€éšããåŒã³åºãããã¹ãã§ã¯ãªããä»ã®ãªããžã§ã¯ãããã·ã°ãã«ãåŒã³åºãããšã¯ã»ãšãã©åžžã«æªãèãã§ãã
ãã ããæ°ããæ§æã䜿çšãããšãæ¥ç¶ãäœæããæç¹ã§ä¿¡å·ã¢ãã¬ã¹ãååŸã§ããã¯ãã§ãã ã³ã³ãã€ã©ã¯ãã·ã°ãã«ã«ã¢ã¯ã»ã¹ã§ããå Žåã«ã®ã¿ãããèš±å¯ããŸãã æžã蟌ã¿ãšã«ãŠã³ã¿ãŒ:: valueChangedã¯ãä¿¡å·ãéããŠããªãå Žåãã³ã³ãã€ã«ãšã©ãŒãçæããŸãã
Qt5ã§ã¯ãä¿¡å·ãä¿è·ãããªãŒãã³ã«å€æŽããå¿ èŠããããŸããã æ®å¿µãªãããããã¯èª°ã§ãä¿¡å·ãçºä¿¡ã§ããããšãæå³ããŸãã ãããä¿®æ£ããæ¹æ³ãèŠã€ãããŸããã§ããã ç§ãã¡ã¯ã emitããŒã¯ãŒãã䜿ã£ãŠããªãã¯ãè©ŠããŸããã ç¹å¥ãªæå³ãè¿ãããšããŸããã ããããäœãããŸããããŸããã§ããã æ°ããæ§æã®å©ç¹ã¯ãä¿¡å·ãçŸåšéããŠãããšãã®åé¡ãå æãããšä¿¡ããŠããŸãã
å Žåã«ãã£ãŠã¯ãä¿¡å·ãéããããšããå§ãããŸãã ããã¯ãããšãã°QAbstractItemModelã®å Žåã§ããããã§ãªãå Žåãéçºè ã¯APIãå¿ èŠãšããªã掟çã¯ã©ã¹ã§ä¿¡å·ãéä¿¡ããåŸåããããŸãã 圌ãã¯ãä¿¡å·ãéããããªããã»ããµããªãã¯ã䜿çšããŸããããæ°ããæ¥ç¶æ§æãç ŽããŸããã
æ°ããããã¯ãå°å ¥ãããŸããã QPrivateSignalã¯ãQ_OBJECTãã¯ãã§éããããŠãããšå®£èšããã空ã®æ§é ã§ãã ä¿¡å·ã®æåŸã®ãã©ã¡ãŒã¿ãŒãšããŠäœ¿çšã§ããŸãã éããããŠããã®ã§ããªããžã§ã¯ãã ããã·ã°ãã«ãåŒã³åºãããã«ãããäœæããæš©å©ãæã£ãŠããŸãã MOC㯠ã眲åæ å ±ãäœæãããšãã«æåŸã®QPrivateSignalåŒæ°ãç¡èŠããŸãã äŸã«ã€ããŠã¯ã qabstractitemmodel.hãåç §ããŠãã ããã
ããå®åçãªã³ãŒã
æ®ãã®ã³ãŒãã¯qobjectdefs_impl.hããã³qobject_impl.hã«ãããŸãã ããã¯åºæ¬çã«éå±ãªå®åã³ãŒãã§ãã ãã®æçš¿ã®è©³çŽ°ã«ã€ããŠã¯è©³ãã説æããŸããããèšåãã䟡å€ã®ããããã€ãã®ãã€ã³ãã«ã€ããŠã¯èª¬æããŸãã
ã¡ã¿ããã°ã©ãã³ã°ãªã¹ã
åè¿°ã®ããã«ãFunctionPointer :: Argumentsã¯åŒæ°ã®ãªã¹ãã§ãã ã³ãŒãã¯ãã®ãªã¹ãã§æ©èœããå¿ èŠããããŸããèŠçŽ ããšã«èŠçŽ ãå埩ãããããã®äžéšã®ã¿ãååŸãããããã®èŠçŽ ãéžæããŸãã ããããQtPrivate :: Listãåã®ãªã¹ããšããŠè¡šçŸã§ããçç±ã§ãã ããã€ãã®ãã«ããŒã¯ã©ã¹ã¯QtPrivate :: List_Selectããã³QtPrivate :: List_Leftã§ãããããã¯ããªã¹ãã®Nçªç®ã®èŠçŽ ãšæåã®Nåã®èŠçŽ ãå«ããªã¹ãã®äžéšãè¿ããŸãã
Listã®å®è£ ã¯ãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€ãã³ãã¬ãŒãããµããŒããããããããµããŒãããªãã³ã³ãã€ã©ãŒã§ã¯ç°ãªããŸãã å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€ãã³ãã¬ãŒãã®å ŽåïŒ
template<typename... T> struct List;
åŒæ°ãªã¹ãã¯ãåã«ãã³ãã¬ãŒããã©ã¡ãŒã¿ãé衚瀺ã«ããŸãã ããšãã°ãåŒæ°ïŒintãQstringãQObject *ïŒãå«ããªã¹ãã®ã¿ã€ãã¯æ¬¡ã®ããã«ãªããŸãã
List<int, QString, QObject *>
å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€ãã³ãã¬ãŒãããªãå Žåãããã¯LISPã¹ã¿ã€ã«ã«ãªããŸãã
template<typename Head, typename Tail > struct List;
Tailã¯ããªã¹ãã®æåŸã«ããä»ã®ãªã¹ããŸãã¯ç¡å¹ã«ããããšãã§ããŸãã ãã®å Žåã®åã®äŸã¯æ¬¡ã®ããã«ãªããŸãã
List<int, List<QString, List<QObject *, void>>>
ApplyReturnValueããªãã¯
FunctionPointer :: callé¢æ°ã§ã¯ãargs [0]ã䜿çšããŠã¹ãããã®æ»ãå€ãååŸããŸãã ã·ã°ãã«ãå€ãè¿ãå Žåãããã¯ã·ã°ãã«ã®æ»ãå€ã®åãæã€ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒã«ãªããŸããããã§ãªãå Žåã¯0ã§ããã¹ããããå€ãè¿ãå Žåããããarg [0]ã«ã³ããŒããå¿ èŠããããŸãã ç¡å¹ã®å ŽåãäœãããŸããã
åé¡ã¯ãvoidãè¿ãé¢æ°ã®æ»ãå€ã䜿çšããããšã¯æ§æçã«æ£ãããªãããšã§ãã 倧éã®ã³ãŒããè€è£œããå¿ èŠããããŸãã1åã¯voidã®æ»ãå€çšã§ããã1ã€ã¯void以å€ã®å€çšã§ãã ããããã³ã³ãæŒç®åã®ãããã§ãã
C ++ã§ã¯ããããè¡ãããšãã§ããŸãã
functionThatReturnsVoid(), somethingElse();
ã³ã³ããã»ãã³ãã³ã«çœ®ãæããããšãã§ããããã¯ãã¹ãŠçŽ æŽãããããšã§ãã void以å€ã§åŒã³åºããšèå³æ·±ããã®ã«ãªããŸãã
functionThatReturnsInt(), somethingElse();
ããã§ã¯ãã³ã³ããåŒã³åºãããã¹ããŒãã¡ã³ãã«ãªãããªãŒããŒããŒãããããšãã§ããŸãã ããã¯ã qobjectdefs_impl.hã§è¡ãããšã§ã ã
template <typename T> struct ApplyReturnValue { void *data; ApplyReturnValue(void *data_) : data(data_) {} }; template<typename T, typename U> void operator,(const T &value, const ApplyReturnValue<U> &container) { if (container.data) *reinterpret_cast<U*>(container.data) = value; } template<typename T> void operator,(T, const ApplyReturnValue<void> &) {}
ApplyReturnValueã¯ãåãªãvoid *ã®ã©ãããŒã§ãã çŸåšãããã¯ç®çã®ãã«ããŒãšã³ãã£ãã£ã§äœ¿çšã§ããŸãã åŒæ°ãªãã®ãã¡ã³ã¯ã¿ãŒã®äŸã次ã«ç€ºããŸãã
static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue<SignalReturnType>(arg[0]); }
ãã®ã³ãŒãã¯ã€ã³ã©ã€ã³ã§ãããããå®è¡æã®ããã©ãŒãã³ã¹ã«é¢ããŠã¯äœãããããŸããã