CMS 3D CMS Logo

MultiMethod.h

Go to the documentation of this file.
00001 #ifndef CLASSLIB_MULTIMETHOD_H
00002 # define CLASSLIB_MULTIMETHOD_H
00003 
00004 //<<<<<< INCLUDES                                                       >>>>>>
00005 
00006 # include "classlib/utils/XTypeInfo.h"
00007 # include "classlib/utils/PODVector.h"
00008 # include "classlib/utils/Macros.h"
00009 
00010 namespace lat {
00011 //<<<<<< PUBLIC DEFINES                                                 >>>>>>
00012 
00013 // Usage:
00014 //   x.h:
00015 //     MULTIMETHOD_DECLARE (extern API,Point,intersect,2,0,
00016 //                          (Trajectory,Surface));
00017 //   x.cc:
00018 //     MULTIMETHOD_DEFINE (::, intersect);
00019 //      NB: `::' because the multi-method is at global scope!
00020 //
00021 //   y.cc:
00022 //     MMM_DEFUN_FUNC (Point,::,intersect,(Line *line, Plane *plane))
00023 //     { Point p = /* use `line' and `plane' */; return p; }
00024 //
00025 //      NB: `::' is the scope of the multi-method, in this case global.
00026 //
00027 // or:
00028 //   X.h:
00029 //     class X {
00030 //     public:
00031 //        MULTIMETHOD_DECLARE(static,Point,intersect,2,0,(Trajectory,Surface));
00032 //     };
00033 //   X.cc:
00034 //     MULTIMETHOD_DEFINE (X::,intersect);
00035 //      NB: `X::' is the scope of the multi-method.
00036 //
00037 //   Y.h:
00038 //     class Y : public X {
00039 //     public: // <-- multimethod members *must* be public
00040 //        static MMM_DECLARE (Point,intersect,(Line *,Plane *));
00041 //     };
00042 //   Y.cc:
00043 //     MMM_DEFUN_METHOD(Point,X::,Y::,intersect, (Line *line, Plane *plane))
00044 //     { Point p = /* use `line' and `plane' */; return p; }
00045 //
00046 //      NB: `X::' is the scope of the multi-method.  `Y::' is the
00047 //          scope of the family member.
00048 
00049 // All this would be so simple if we had GNU or ISO C 9x vararg macros...
00050 #  define MULTIMETHOD_ARGS_1_0(V1)              V1
00051 #  define MULTIMETHOD_ARGS_1_1(V1,A1)           V1,             A1
00052 #  define MULTIMETHOD_ARGS_1_2(V1,A1,A2)        V1,             A1, A2
00053 #  define MULTIMETHOD_ARGS_2_0(V1,V2)           V1, V2
00054 #  define MULTIMETHOD_ARGS_2_1(V1,V2,A1)        V1, V2,         A1
00055 #  define MULTIMETHOD_ARGS_2_2(V1,V2,A1,A2)     V1, V2,         A1, A2
00056 #  define MULTIMETHOD_ARGS_3_0(V1,V2,V3)        V1, V2, V3
00057 #  define MULTIMETHOD_ARGS_3_1(V1,V2,V3,A1)     V1, V2, V3,     A1
00058 #  define MULTIMETHOD_ARGS_3_2(V1,V2,V3,A1,A2)  V1, V2, V3,     A1, A2
00059 
00060 #  define MULTIMETHOD_DECLARE(ext,rettype,name,nvirt,nnonvirt,args)     \
00061     ext lat::MultiMethod::Definition name ## Def;                       \
00062     typedef lat::MultiMethod_##nvirt##_##nnonvirt<                      \
00063       rettype, MULTIMETHOD_ARGS_##nvirt##_##nnonvirt args               \
00064     > name##Type;                                                       \
00065     ext name##Type name
00066 
00067 #  define MULTIMETHOD_DEFINE(scope,name)                                \
00068     lat::MultiMethod::Definition scope name ## Def =            \
00069       { #name, 0, false, false, 0, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0, 0 };  \
00070     scope name ## Type scope name (&name ##Def)
00071 
00072 #  define MMM_SYM(pre,line,post)                CLASSLIB_name3(pre,line,post)
00073 #  define MMM_DECLARE(ret,name,proto)           ret mmm_##name proto
00074 #  define MMM_DECLARE_STUB(mscope,scope,name,proto,regsym)              \
00075     static lat::MultiMethodMember< mscope name##Type,proto,     \
00076         &scope mmm_##name, &mscope name##Def> regsym
00077 #  define MMM_DEFUN_METHOD(ret,mscope,scope,name,proto)                 \
00078     MMM_DECLARE_STUB(mscope,scope,name,ret (*) proto,                   \
00079                      MMM_SYM(name,Init,__LINE__));                      \
00080     ret scope mmm_##name proto
00081 #  define MMM_DEFUN_FUNC(ret,mscope,name,proto)                         \
00082     ret mmm_##name proto;                                               \
00083     MMM_DECLARE_STUB(mscope,::,name,ret (*) proto,                      \
00084                      MMM_SYM(name,Init,__LINE__));                      \
00085     ret mmm_##name proto
00086 
00087 //<<<<<< PUBLIC CONSTANTS                                               >>>>>>
00088 //<<<<<< PUBLIC TYPES                                                   >>>>>>
00089 //<<<<<< PUBLIC VARIABLES                                               >>>>>>
00090 //<<<<<< PUBLIC FUNCTIONS                                               >>>>>>
00091 //<<<<<< CLASS DECLARATIONS                                             >>>>>>
00092 
00154 class MultiMethod : protected XTypeInfo::Monitor
00155 {
00156 public:
00157     struct Definition;
00158 #if ! HAVE_BROKEN_CLASS_ACCESS
00159 protected:
00160 #endif
00161     struct Score;
00162 #if ! HAVE_BROKEN_CLASS_ACCESS
00163 private:
00164 #endif
00165     struct Member;
00166     struct ScoreHunk;
00167     struct EntryHunk;
00168     struct Entry;
00169 
00170     friend struct Definition;
00171     friend struct Member;
00172     friend struct ScoreHunk;
00173     friend struct EntryHunk;
00174     friend struct Entry;
00175 public:
00181     typedef void (*MemberFunction) (void);
00182 
00195     struct Definition
00196     {
00199         const char              *m_name;
00200 
00203         STDC::size_t            m_key;
00204 
00207         bool                    m_hooked;
00208 
00212         bool                    m_dirty;
00213 
00217         STDC::size_t            m_generation;
00218 
00220         STDC::size_t            m_formals;
00221 
00225         XTypeInfo::ClassDef     **m_formalTypes;
00226 
00227 
00230         PODVector<Member>::Data m_family;
00231 
00233         STDC::size_t            m_familyMaxSize;
00234 
00236         STDC::size_t            m_familyMaxCapacity;
00237 
00247         ScoreHunk               *m_scoreHunks;
00248 
00251         EntryHunk               *m_entryHunks;
00252 
00256         Entry                   *m_freeEntries;
00257 
00258         void                    extend (MemberFunction function,
00259                                         XTypeInfo::ClassDef **formalTypes);
00260         void                    remove (MemberFunction function);
00261     };
00262 
00263 #if ! HAVE_BROKEN_CLASS_ACCESS
00264 protected:
00265 #endif
00266 
00285     struct Score
00286     {
00294         unsigned short          m_distance;
00295 
00298         unsigned short          m_index;
00299     };
00300 
00301     MultiMethod (void);
00302     ~MultiMethod (void);
00303     
00304     void                        initialise (Definition *data,
00305                                             STDC::size_t formals,
00306                                             XTypeInfo::ClassDef **formalTypes);
00307 
00308     MemberFunction              dispatch (XTypeInfo **actualTypes,
00309                                           Score **candidates,
00310                                           Score *best) const;
00311 
00312 #if ! HAVE_BROKEN_CLASS_ACCESS
00313 private:
00314 #endif
00315 
00321     enum { INITIAL_FAMILY_SIZE = 32 };          // FIXME: STDC::size_t
00322 
00324     enum { SCORE_HUNK_SIZE = 64 };              // FIXME: STDC::size_t
00325 
00327     enum { ENTRY_HUNK_SIZE = 32 };              // FIXME: STDC::size_t
00328 
00331     enum { LAST_SCORE = USHRT_MAX };            // FIXME: unsigned short
00332 
00336     enum { INFINITE_DISTANCE = USHRT_MAX };     // FIXME: unsigned short
00337 
00339     struct Member
00340     {
00342         MemberFunction          m_function;
00346         XTypeInfo::ClassDef     **m_formalTypes;
00347     };
00348 
00350     struct ScoreHunk
00351     {
00352         ScoreHunk               *m_next;        //< Next hunk
00353         Score                   *m_scores;      //< The score vector
00354         Score                   *m_free;        //< List of free scores
00355         STDC::size_t            m_capacity;     //< Number of scores allocated
00356     };
00357 
00359     struct EntryHunk
00360     {
00361         EntryHunk               *m_next;        //< Next hunk
00362         Entry                   *m_entries;     //< The entry vector
00363         Entry                   *m_free;        //< List of free entries
00364         STDC::size_t            m_capacity;     //< Number of entries allocated
00365     };
00366 
00385     struct Entry
00386     {
00391         Entry                   *m_next;
00392 
00395         STDC::size_t            m_key;
00396 
00398         STDC::size_t            m_formal;
00399 
00403         STDC::size_t            m_generation;
00404 
00416         Score                   *m_scores;
00417     };
00418 
00419     // global data
00420     static XTypeInfo::ExtensionKey
00421                                 extensionKey (void);
00422     static STDC::size_t         methodKey (void);
00423 
00424     // memory management
00425     ScoreHunk *                 createScoreHunk (STDC::size_t min) const;
00426     void                        freeScoreHunks (void) const;
00427     Score *                     allocateScores (STDC::size_t n) const;
00428 
00429     EntryHunk *                 createEntryHunk (void) const;
00430     void                        freeEntryHunks (void) const;
00431     Entry *                     allocateEntry (void) const;
00432     void                        freeEntry (Entry *item) const;
00433 
00434     // dynamic type management
00435     STDC::size_t                relatedFormal (const XTypeInfo *type) const;
00436     static Entry *              findTypeEntries (const XTypeInfo *type,
00437                                                  Entry *&previous,
00438                                                  STDC::size_t key,
00439                                                  STDC::size_t formal
00440                                                  = STDC::size_t(-1));
00441 
00442     void                        typePrepare (STDC::size_t formal,
00443                                              XTypeInfo *type) const;
00444     bool                        typeClean (STDC::size_t formal,
00445                                            XTypeInfo *type) const;
00446     virtual void                typeHook (XTypeInfo *type);
00447     virtual void                typeUnhook (XTypeInfo *type);
00448 
00449     static bool                 orderScores (const Score &x, const Score &y);
00450     void                        cleanScores (const XTypeInfo *type) const;
00451     void                        buildScores (const XTypeInfo *type) const;
00452     void                        newGeneration (void) const;
00453     void                        regenerate (const XTypeInfo *type) const;
00454 
00455     // dispatching
00456     void                        noViableAlt (XTypeInfo **actuals) const;
00457     void                        ambiguity (XTypeInfo **actuals,
00458                                            Score **candidates,
00459                                            Score *best) const;
00460 
00461     // actual data members -- forwarded
00462     Definition                  *m_data;
00463 
00464     // undefined, no semantics
00465     MultiMethod (const MultiMethod &);
00466     MultiMethod &operator= (const MultiMethod &);
00467 };
00468 
00472 // Classes for the real multi-methods the user will end up declaring;
00473 // see MULTIMETHOD_DECLARE on how these end up getting used.  These
00474 // classes know the actual arguments used for that specific method,
00475 // and take care of initialising the method.  They also record just
00476 // enough information for the black magic below to recover enough
00477 // details when members for this family are registered.
00478 template <class R, class V1>
00479 class MultiMethod_1_0 : public MultiMethod
00480 {
00481 public:
00482     static const int    NVIRT = 1;
00483     static const int    NNONVIRT = 0;
00484     typedef R           RTYPE;
00485     typedef V1          VTYPE1;
00486 
00487     MultiMethod_1_0 (Definition *def);
00488     R operator() (V1 *v1);
00489 
00490 private:
00491     XTypeInfo::ClassDef *m_formals [1];
00492 };
00493 
00494 template <class R, class V1, class T1>
00495 class MultiMethod_1_1 : public MultiMethod
00496 {
00497 public:
00498     static const int    NVIRT = 1;
00499     static const int    NNONVIRT = 1;
00500     typedef R           RTYPE;
00501     typedef V1          VTYPE1;
00502     typedef T1          NONVTYPE1;
00503 
00504     MultiMethod_1_1 (Definition *def);
00505     R operator() (V1 *v1, T1 t1);
00506 
00507 private:
00508     XTypeInfo::ClassDef *m_formals [1];
00509 };
00510 
00511 template <class R, class V1, class T1, class T2>
00512 class MultiMethod_1_2 : public MultiMethod
00513 {
00514 public:
00515     static const int    NVIRT = 1;
00516     static const int    NNONVIRT = 2;
00517     typedef R           RTYPE;
00518     typedef V1          VTYPE1;
00519     typedef T1          NONVTYPE1;
00520     typedef T2          NONVTYPE2;
00521 
00522     MultiMethod_1_2 (Definition *def);
00523     R operator() (V1 *v1, T1 t1, T2 t2);
00524 
00525 private:
00526     XTypeInfo::ClassDef *m_formals [1];
00527 };
00528 
00532 template <class R, class V1, class V2>
00533 class MultiMethod_2_0 : public MultiMethod
00534 {
00535 public:
00536     static const int    NVIRT = 2;
00537     static const int    NNONVIRT = 0;
00538     typedef R           RTYPE;
00539     typedef V1          VTYPE1;
00540     typedef V2          VTYPE2;
00541 
00542     MultiMethod_2_0 (Definition *def);
00543     R operator() (V1 *v1, V2 *v2);
00544 
00545 private:
00546     XTypeInfo::ClassDef *m_formals [2];
00547 };
00548 
00549 template <class R, class V1, class V2, class T1>
00550 class MultiMethod_2_1 : public MultiMethod
00551 {
00552 public:
00553     static const int    NVIRT = 2;
00554     static const int    NNONVIRT = 1;
00555     typedef R           RTYPE;
00556     typedef V1          VTYPE1;
00557     typedef V2          VTYPE2;
00558     typedef T1          NONVTYPE1;
00559 
00560     MultiMethod_2_1 (Definition *def);
00561     R operator() (V1 *v1, V2 *v2, T1 t1);
00562 
00563 private:
00564     XTypeInfo::ClassDef *m_formals [2];
00565 };
00566 
00567 template <class R, class V1, class V2, class T1, class T2>
00568 class MultiMethod_2_2 : public MultiMethod
00569 {
00570 public:
00571     static const int    NVIRT = 2;
00572     static const int    NNONVIRT = 2;
00573     typedef R           RTYPE;
00574     typedef V1          VTYPE1;
00575     typedef V2          VTYPE2;
00576     typedef T1          NONVTYPE1;
00577     typedef T2          NONVTYPE2;
00578 
00579     MultiMethod_2_2 (Definition *def);
00580     R operator() (V1 *v1, V2 *v2, T1 t1, T2 t2);
00581 
00582 private:
00583     XTypeInfo::ClassDef *m_formals [2];
00584 };
00585 
00589 template <class R, class V1, class V2, class V3>
00590 class MultiMethod_3_0 : public MultiMethod
00591 {
00592 public:
00593     static const int    NVIRT = 3;
00594     static const int    NNONVIRT = 0;
00595     typedef R           RTYPE;
00596     typedef V1          VTYPE1;
00597     typedef V2          VTYPE2;
00598     typedef V3          VTYPE3;
00599 
00600     MultiMethod_3_0 (Definition *def);
00601     R operator() (V1 *v1, V2 *v2, V3 *v3);
00602 
00603 private:
00604     XTypeInfo::ClassDef *m_formals [3];
00605 };
00606 
00607 template <class R, class V1, class V2, class V3, class T1>
00608 class MultiMethod_3_1 : public MultiMethod
00609 {
00610 public:
00611     static const int    NVIRT = 3;
00612     static const int    NNONVIRT = 1;
00613     typedef R           RTYPE;
00614     typedef V1          VTYPE1;
00615     typedef V2          VTYPE2;
00616     typedef V3          VTYPE3;
00617     typedef T1          NONVTYPE1;
00618 
00619     MultiMethod_3_1 (Definition *def);
00620     R operator() (V1 *v1, V2 *v2, V3 *v3, T1 t1);
00621 
00622 private:
00623     XTypeInfo::ClassDef *m_formals [3];
00624 };
00625 
00626 template <class R, class V1, class V2, class V3, class T1, class T2>
00627 class MultiMethod_3_2 : public MultiMethod
00628 {
00629 public:
00630     static const int    NVIRT = 3;
00631     static const int    NNONVIRT = 2;
00632     typedef R           RTYPE;
00633     typedef V1          VTYPE1;
00634     typedef V2          VTYPE2;
00635     typedef V3          VTYPE3;
00636     typedef T1          NONVTYPE1;
00637     typedef T2          NONVTYPE2;
00638 
00639     MultiMethod_3_2 (Definition *def);
00640     R operator() (V1 *v1, V2 *v2, V3 *v3, T1 t1, T2 t2);
00641 
00642 private:
00643     XTypeInfo::ClassDef *m_formals [3];
00644 };
00645 
00649 
00662 template <int NV, int NNV, class M, class R, class P> class MultiMethodCarrier {};
00663 
00695 template <class M, class P, P F, MultiMethod::Definition *D>
00696 struct MultiMethodMember {
00697     typedef MultiMethodCarrier<M::NVIRT, M::NNONVIRT, M, typename M::RTYPE, P> Carrier;
00698     MultiMethodMember (void)  { MultiMethodStub ((Carrier *)0)->init(D,F); }
00699     ~MultiMethodMember (void) { MultiMethodStub ((Carrier *)0)->reset(D); }
00700 };
00701 
00703 // classes for internal template magic ugliness; see MultiMethodStub
00704 // and MultiMethodMember for the details on how these are used.
00705 template <class M, class V1>
00706 struct MultiMethodMemberStub_1_0 {
00707     typedef typename M::RTYPE (*F) (V1 *);
00708     static F s_f;
00709     static void init (MultiMethod::Definition *d, F f)
00710         { static XTypeInfo::ClassDef *actuals [M::NVIRT] = { xtypedata(V1) };
00711           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00712     static void reset (MultiMethod::Definition *d)
00713         { d->remove ((MultiMethod::MemberFunction) &stub); }
00714     static typename M::RTYPE stub (typename M::VTYPE1 *v1)
00715         { return s_f (dynamic_cast<V1 *> (v1)); }
00716 };
00717 
00718 template <class M, class V1>
00719 struct MultiMethodMemberStub_1_1 {
00720     typedef typename M::RTYPE (*F) (V1 *, typename M::NONVTYPE1);
00721     static F s_f;
00722     static void init (MultiMethod::Definition *d, F f)
00723         { static XTypeInfo::ClassDef *actuals [M::NVIRT] = { xtypedata(V1) };
00724           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00725     static void reset (MultiMethod::Definition *d)
00726         { d->remove ((MultiMethod::MemberFunction) &stub); }
00727     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00728                                    typename M::NONVTYPE1 a1)
00729         { return s_f (dynamic_cast<V1 *> (v1), a1); }
00730 };
00731 
00732 template <class M, class V1>
00733 struct MultiMethodMemberStub_1_2 {
00734     typedef typename M::RTYPE (*F) (V1 *, typename M::NONVTYPE1,
00735                                     typename M::NONVTYPE2);
00736     static F s_f;
00737     static void init (MultiMethod::Definition *d, F f)
00738         { static XTypeInfo::ClassDef *actuals [M::NVIRT] = { xtypedata(V1) };
00739           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00740     static void reset (MultiMethod::Definition *d)
00741         { d->remove ((MultiMethod::MemberFunction) &stub); }
00742     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00743                                    typename M::NONVTYPE1 a1,
00744                                    typename M::NONVTYPE2 a2)
00745         { return s_f (dynamic_cast<V1 *> (v1), a1, a2); }
00746 };
00747 
00749 template <class M, class V1, class V2>
00750 struct MultiMethodMemberStub_2_0 {
00751     typedef typename M::RTYPE (*F) (V1 *, V2 *);
00752     static F s_f;
00753     static void init (MultiMethod::Definition *d, F f)
00754         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00755               = { xtypedata(V1), xtypedata(V2) };
00756           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00757     static void reset (MultiMethod::Definition *d)
00758         { d->remove ((MultiMethod::MemberFunction) &stub); }
00759     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00760                                    typename M::VTYPE2 *v2)
00761         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2)); }
00762 };
00763 
00764 template <class M, class V1, class V2>
00765 struct MultiMethodMemberStub_2_1 {
00766     typedef typename M::RTYPE (*F) (V1 *, V2 *, typename M::NONVTYPE1);
00767     static F s_f;
00768     static void init (MultiMethod::Definition *d, F f)
00769         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00770               = { xtypedata(V1), xtypedata(V2) };
00771           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00772     static void reset (MultiMethod::Definition *d)
00773         { d->remove ((MultiMethod::MemberFunction) &stub); }
00774     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00775                                    typename M::VTYPE2 *v2,
00776                                    typename M::NONVTYPE1 a1)
00777         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2), a1); }
00778 };
00779 
00780 template <class M, class V1, class V2>
00781 struct MultiMethodMemberStub_2_2 {
00782     typedef typename M::RTYPE (*F) (V1 *, V2 *, typename M::NONVTYPE1,
00783                                     typename M::NONVTYPE2);
00784     static F s_f;
00785     static void init (MultiMethod::Definition *d, F f)
00786         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00787               = { xtypedata(V1), xtypedata(V2) };
00788           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00789     static void reset (MultiMethod::Definition *d)
00790         { d->remove ((MultiMethod::MemberFunction) &stub); }
00791     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00792                                    typename M::VTYPE2 *v2,
00793                                    typename M::NONVTYPE1 a1,
00794                                    typename M::NONVTYPE2 a2)
00795         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2),
00796                       a1, a2); }
00797 };
00798 
00800 template <class M, class V1, class V2, class V3>
00801 struct MultiMethodMemberStub_3_0 {
00802     typedef typename M::RTYPE (*F) (V1 *, V2 *, V3 *);
00803     static F s_f;
00804     static void init (MultiMethod::Definition *d, F f)
00805         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00806               = { xtypedata(V1), xtypedata(V2), xtypedata(V3) };
00807           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00808     static void reset (MultiMethod::Definition *d)
00809         { d->remove ((MultiMethod::MemberFunction) &stub); }
00810     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00811                                    typename M::VTYPE2 *v2,
00812                                    typename M::VTYPE3 *v3)
00813         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2),
00814                       dynamic_cast<V3 *> (v3)); }
00815 };
00816 
00817 template <class M, class V1, class V2, class V3>
00818 struct MultiMethodMemberStub_3_1 {
00819     typedef typename M::RTYPE (*F) (V1 *, V2 *, V3 *, typename M::NONVTYPE1);
00820     static F s_f;
00821     static void init (MultiMethod::Definition *d, F f)
00822         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00823               = { xtypedata(V1), xtypedata(V2), xtypedata(V3) };
00824           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00825     static void reset (MultiMethod::Definition *d)
00826         { d->remove ((MultiMethod::MemberFunction) &stub); }
00827     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00828                                    typename M::VTYPE2 *v2,
00829                                    typename M::VTYPE3 *v3,
00830                                    typename M::NONVTYPE1 a1)
00831         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2),
00832                       dynamic_cast<V3 *> (v3), a1); }
00833 };
00834 
00835 template <class M, class V1, class V2, class V3>
00836 struct MultiMethodMemberStub_3_2 {
00837     typedef typename M::RTYPE (*F) (V1 *, V2 *, V3 *, typename M::NONVTYPE1,
00838                                     typename M::NONVTYPE2);
00839     static F s_f;
00840     static void init (MultiMethod::Definition *d, F f)
00841         { static XTypeInfo::ClassDef *actuals [M::NVIRT]
00842               = { xtypedata(V1), xtypedata(V2), xtypedata(V3) };
00843           s_f = f; d->extend ((MultiMethod::MemberFunction) &stub, actuals); }
00844     static void reset (MultiMethod::Definition *d)
00845         { d->remove ((MultiMethod::MemberFunction) &stub); }
00846     static typename M::RTYPE stub (typename M::VTYPE1 *v1,
00847                                    typename M::VTYPE2 *v2,
00848                                    typename M::VTYPE3 *v3,
00849                                    typename M::NONVTYPE1 a1,
00850                                    typename M::NONVTYPE2 a2)
00851         { return s_f (dynamic_cast<V1 *> (v1), dynamic_cast<V2 *> (v2),
00852                       dynamic_cast<V3 *> (v3), a1, a2); }
00853 };
00854 
00856 template <class M, class V1>
00857 typename MultiMethodMemberStub_1_0<M,V1>::F
00858 MultiMethodMemberStub_1_0<M,V1>::s_f = 0;
00859 template <class M, class V1>
00860 typename MultiMethodMemberStub_1_1<M,V1>::F
00861 MultiMethodMemberStub_1_1<M,V1>::s_f = 0;
00862 template <class M, class V1>
00863 typename MultiMethodMemberStub_1_2<M,V1>::F
00864 MultiMethodMemberStub_1_2<M,V1>::s_f = 0;
00865 
00866 template <class M, class V1, class V2>
00867 typename MultiMethodMemberStub_2_0<M,V1,V2>::F
00868 MultiMethodMemberStub_2_0<M,V1,V2>::s_f = 0;
00869 template <class M, class V1, class V2>
00870 typename MultiMethodMemberStub_2_1<M,V1,V2>::F
00871 MultiMethodMemberStub_2_1<M,V1,V2>::s_f = 0;
00872 template <class M, class V1, class V2>
00873 typename MultiMethodMemberStub_2_2<M,V1,V2>::F
00874 MultiMethodMemberStub_2_2<M,V1,V2>::s_f = 0;
00875 
00876 template <class M, class V1, class V2, class V3>
00877 typename MultiMethodMemberStub_3_0<M,V1,V2,V3>::F
00878 MultiMethodMemberStub_3_0<M,V1,V2,V3>::s_f = 0;
00879 template <class M, class V1, class V2, class V3>
00880 typename MultiMethodMemberStub_3_1<M,V1,V2,V3>::F
00881 MultiMethodMemberStub_3_1<M,V1,V2,V3>::s_f = 0;
00882 template <class M, class V1, class V2, class V3>
00883 typename MultiMethodMemberStub_3_2<M,V1,V2,V3>::F
00884 MultiMethodMemberStub_3_2<M,V1,V2,V3>::s_f = 0;
00885 
00886 //<<<<<< INLINE PUBLIC FUNCTIONS                                        >>>>>>
00887 //<<<<<< INLINE MEMBER FUNCTIONS                                        >>>>>>
00888 
00889 template <class R, class V1>
00890 inline
00891 MultiMethod_1_0<R,V1>::MultiMethod_1_0 (Definition *def)
00892 {
00893     m_formals [0] = xtypedata (V1);
00894     initialise (def, 1, m_formals);
00895 }
00896 
00897 template <class R, class V1>
00898 inline R
00899 MultiMethod_1_0<R,V1>::operator() (V1 *v1)
00900 {
00901     XTypeInfo           *actuals [1] = { xtypeid (*v1) };
00902     Score               *candidates [1];
00903     Score               best [1];
00904     MemberFunction      match;
00905 
00906     match = dispatch (actuals, candidates, best);
00907     return (*reinterpret_cast<R (*) (V1 *)> (match))
00908         (v1);
00909 }
00910 
00912 
00913 template <class R, class V1, class T1>
00914 inline
00915 MultiMethod_1_1<R,V1,T1>::MultiMethod_1_1 (Definition *def)
00916 {
00917     m_formals [0] = xtypedata (V1);
00918     initialise (def, 1, m_formals);
00919 }
00920 
00921 template <class R, class V1, class T1>
00922 inline R
00923 MultiMethod_1_1<R,V1,T1>::operator() (V1 *v1, T1 t1)
00924 {
00925     XTypeInfo           *actuals [1] = { xtypeid (*v1) };
00926     Score               *candidates [1];
00927     Score               best [1];
00928     MemberFunction      match;
00929 
00930     match = dispatch (actuals, candidates, best);
00931     return (*reinterpret_cast<R (*) (V1 *, T1)> (match))
00932         (v1, t1);
00933 }
00934 
00936 template <class R, class V1, class T1, class T2>
00937 inline
00938 MultiMethod_1_2<R,V1,T1,T2>::MultiMethod_1_2 (Definition *def)
00939 {
00940     m_formals [0] = xtypedata (V1);
00941     initialise (def, 1, m_formals);
00942 }
00943 
00944 template <class R, class V1, class T1, class T2>
00945 inline R
00946 MultiMethod_1_2<R,V1,T1,T2>::operator() (V1 *v1, T1 t1, T2 t2)
00947 {
00948     XTypeInfo           *actuals [1] = { xtypeid (*v1) };
00949     Score               *candidates [1];
00950     Score               best [1];
00951     MemberFunction      match;
00952 
00953     match = dispatch (actuals, candidates, best);
00954     return (*reinterpret_cast<R (*) (V1 *, T1, T2)> (match))
00955         (v1, t1, t2);
00956 }
00957 
00961 template <class R, class V1, class V2>
00962 inline
00963 MultiMethod_2_0<R,V1,V2>::MultiMethod_2_0 (Definition *def)
00964 {
00965     m_formals [0] = xtypedata (V1);
00966     m_formals [1] = xtypedata (V2);
00967     initialise (def, 2, m_formals);
00968 }
00969 
00970 template <class R, class V1, class V2>
00971 inline R
00972 MultiMethod_2_0<R,V1,V2>::operator() (V1 *v1, V2 *v2)
00973 {
00974     XTypeInfo           *actuals [2] = { xtypeid (*v1), xtypeid (*v2) };
00975     Score               *candidates [2];
00976     Score               best [2];
00977     MemberFunction      match;
00978 
00979     match = dispatch (actuals, candidates, best);
00980     return (*reinterpret_cast<R (*) (V1 *, V2 *)> (match))
00981         (v1, v2);
00982 }
00983 
00985 template <class R, class V1, class V2, class T1>
00986 inline
00987 MultiMethod_2_1<R,V1,V2,T1>::MultiMethod_2_1 (Definition *def)
00988 {
00989     m_formals [0] = xtypedata (V1);
00990     m_formals [1] = xtypedata (V2);
00991     initialise (def, 2, m_formals);
00992 }
00993 
00994 template <class R, class V1, class V2, class T1>
00995 inline R
00996 MultiMethod_2_1<R,V1,V2,T1>::operator() (V1 *v1, V2 *v2, T1 t1)
00997 {
00998     XTypeInfo           *actuals [2] = { xtypeid (*v1), xtypeid (*v2) };
00999     Score               *candidates [2];
01000     Score               best [2];
01001     MemberFunction      match;
01002 
01003     match = dispatch (actuals, candidates, best);
01004     return (*reinterpret_cast<R (*) (V1 *, V2 *, T1)> (match))
01005         (v1, v2, t1);
01006 }
01007 
01009 template <class R, class V1, class V2, class T1, class T2>
01010 inline
01011 MultiMethod_2_2<R,V1,V2,T1,T2>::MultiMethod_2_2 (Definition *def)
01012 {
01013     m_formals [0] = xtypedata (V1);
01014     m_formals [1] = xtypedata (V2);
01015     initialise (def, 2, m_formals);
01016 }
01017 
01018 template <class R, class V1, class V2, class T1, class T2>
01019 inline R
01020 MultiMethod_2_2<R,V1,V2,T1,T2>::operator() (V1 *v1, V2 *v2, T1 t1, T2 t2)
01021 {
01022     XTypeInfo           *actuals [2] = { xtypeid (*v1), xtypeid (*v2) };
01023     Score               *candidates [2];
01024     Score               best [2];
01025     MemberFunction      match;
01026 
01027     match = dispatch (actuals, candidates, best);
01028     return (*reinterpret_cast<R (*) (V1 *, V2 *, T1, T2)> (match))
01029         (v1, v2, t1, t2);
01030 }
01031 
01035 template <class R, class V1, class V2, class V3>
01036 inline
01037 MultiMethod_3_0<R,V1,V2,V3>::MultiMethod_3_0 (Definition *def)
01038 {
01039     m_formals [0] = xtypedata (V1);
01040     m_formals [1] = xtypedata (V2);
01041     m_formals [3] = xtypedata (V3);
01042     initialise (def, 3, m_formals);
01043 }
01044 
01045 template <class R, class V1, class V2, class V3>
01046 inline R
01047 MultiMethod_3_0<R,V1,V2,V3>::operator() (V1 *v1, V2 *v2, V3 *v3)
01048 {
01049     XTypeInfo           *actuals [3] = { xtypeid (*v1), xtypeid (*v2), xtypeid (*v3) };
01050     Score               *candidates [3];
01051     Score               best [3];
01052     MemberFunction      match;
01053 
01054     match = dispatch (actuals, candidates, best);
01055     return (*reinterpret_cast<R (*) (V1 *, V2 *, V3 *)> (match))
01056         (v1, v2, v3);
01057 }
01058 
01060 template <class R, class V1, class V2, class V3, class T1>
01061 inline
01062 MultiMethod_3_1<R,V1,V2,V3,T1>::MultiMethod_3_1 (Definition *def)
01063 {
01064     m_formals [0] = xtypedata (V1);
01065     m_formals [1] = xtypedata (V2);
01066     m_formals [3] = xtypedata (V3);
01067     initialise (def, 3, m_formals);
01068 }
01069 
01070 template <class R, class V1, class V2, class V3, class T1>
01071 inline R
01072 MultiMethod_3_1<R,V1,V2,V3,T1>::operator() (V1 *v1, V2 *v2, V3 *v3, T1 t1)
01073 {
01074     XTypeInfo           *actuals [3] = { xtypeid (*v1), xtypeid (*v2), xtypeid (*v3) };
01075     Score               *candidates [3];
01076     Score               best [3];
01077     MemberFunction      match;
01078 
01079     match = dispatch (actuals, candidates, best);
01080     return (*reinterpret_cast<R (*) (V1 *, V2 *, V3 *, T1)> (match))
01081         (v1, v2, v3, t1);
01082 }
01083 
01085 template <class R, class V1, class V2, class V3, class T1, class T2>
01086 inline
01087 MultiMethod_3_2<R,V1,V2,V3,T1,T2>::MultiMethod_3_2 (Definition *def)
01088 {
01089     m_formals [0] = xtypedata (V1);
01090     m_formals [1] = xtypedata (V2);
01091     m_formals [3] = xtypedata (V3);
01092     initialise (def, 3, m_formals);
01093 }
01094 
01095 template <class R, class V1, class V2, class V3, class T1, class T2>
01096 inline R
01097 MultiMethod_3_2<R,V1,V2,V3,T1,T2>::operator() (V1 *v1, V2 *v2, V3 *v3, T1 t1, T2 t2)
01098 {
01099     XTypeInfo           *actuals [3] = { xtypeid (*v1), xtypeid (*v2), xtypeid (*v3) };
01100     Score               *candidates [3];
01101     Score               best [3];
01102     MemberFunction      match;
01103 
01104     match = dispatch (actuals, candidates, best);
01105     return (*reinterpret_cast<R (*) (V1 *, V2 *, V3 *, T1, T2)> (match))
01106         (v1, v2, v3, t1, t2);
01107 }
01108 
01112 // Ugly magic template function to select the right stub type based on
01113 // the type of the member function.  The type of the member function
01114 // is the last argument of MultiMethodCarrier; we select the right
01115 // stub class here based on that function prototype (and pass it all
01116 // the relevant information).
01117 //
01118 // Note that the returned null pointer is never used -- we are only
01119 // interested in the return type.  We cannot actually name the return
01120 // type in MultiMethodMember (we can only use an expression, not a
01121 // declaration), so we use a trick: everything interesting in the
01122 // returned stub class type is actually class-static.  So even though
01123 // we nominally dereference the returned pointer, the compiler really
01124 // never does it and the code is safe!  (I told you this was ugly...
01125 // Now you wish you never would have heard.)
01126 //
01127 // Note also that MSVC++ 7 chokes on `typename M::something' when used
01128 // in the prototype argument list, so we have to use ugly magic to get
01129 // M::RTYPE and M::NONVTYPEn.  For return type we dig the actual type
01130 // out in the caller and it gets passed in with MultiMethodCarrier.
01131 // For NONVTYPEn we just accept anything and make sure in the
01132 // function body that we got the right match.
01133 template <class M, class R, class V1>
01134 inline MultiMethodMemberStub_1_0<M,V1> *
01135 MultiMethodStub (MultiMethodCarrier<1,0,M,R, R (*) (V1*)> *)
01136 { return 0; }
01137 
01138 template <class M, class R, class V1, class A1>
01139 inline MultiMethodMemberStub_1_1<M,V1> *
01140 MultiMethodStub (MultiMethodCarrier<1,1,M,R, R (*) (V1 *, A1)> *)
01141 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0); return 0; }
01142 
01143 template <class M, class R, class V1, class A1, class A2>
01144 inline MultiMethodMemberStub_1_2<M,V1> *
01145 MultiMethodStub (MultiMethodCarrier<1,2,M,R, R (*) (V1 *, A1, A2)> *)
01146 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0);
01147   (void) static_cast<A2 **> ((typename M::NONVTYPE2 **) 0); return 0; }
01148 
01150 template <class M, class R, class V1, class V2>
01151 inline MultiMethodMemberStub_2_0<M,V1,V2> *
01152 MultiMethodStub (MultiMethodCarrier<2,0,M,R, R (*) (V1 *, V2 *)> *)
01153 { return 0; }
01154 
01155 template <class M, class R, class V1, class V2, class A1>
01156 inline MultiMethodMemberStub_2_1<M,V1,V2> *
01157 MultiMethodStub (MultiMethodCarrier<2,1,M,R, R (*) (V1 *, V2 *, A1)> *)
01158 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0); return 0; }
01159 
01160 template <class M, class R, class V1, class V2, class A1, class A2>
01161 inline MultiMethodMemberStub_2_2<M,V1,V2> *
01162 MultiMethodStub (MultiMethodCarrier<2,2,M,R, R (*) (V1 *, V2 *, A1, A2)> *)
01163 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0);
01164   (void) static_cast<A2 **> ((typename M::NONVTYPE2 **) 0); return 0; }
01165 
01167 template <class M, class R, class V1, class V2, class V3>
01168 inline MultiMethodMemberStub_3_0<M,V1,V2,V3> *
01169 MultiMethodStub (MultiMethodCarrier<3,0,M,R, R (*) (V1 *, V2 *, V3 *)> *)
01170 { return 0; }
01171 
01172 template <class M, class R, class V1, class V2, class V3, class A1>
01173 inline MultiMethodMemberStub_3_1<M,V1,V2,V3> *
01174 MultiMethodStub (MultiMethodCarrier<3,1,M,R, R (*) (V1 *, V2 *, V3 *, A1)> *)
01175 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0); return 0; }
01176 
01177 template <class M, class R, class V1, class V2, class V3, class A1, class A2>
01178 inline MultiMethodMemberStub_3_2<M,V1,V2,V3> *
01179 MultiMethodStub (MultiMethodCarrier<3,2,M,R, R (*) (V1 *, V2 *, V3 *, A1, A2)> *)
01180 { (void) static_cast<A1 **> ((typename M::NONVTYPE1 **) 0);
01181   (void) static_cast<A2 **> ((typename M::NONVTYPE2 **) 0); return 0; }
01182 
01183 } // namespace lat
01184 #endif // CLASSLIB_MULTIMETHOD_H

Generated on Tue Jun 9 17:38:54 2009 for CMSSW by  doxygen 1.5.4