4 /* Macros to declare inheriting types, and to (down-)cast and up-cast. */
6 #define STATIC_CAST(to, obj) static_cast<to*>(obj)
7 #define STATIC_UPCAST(to, from, obj) static_cast<to*>(obj)
10 #define DERIVE_FROM_TYPE(t) t t##_parent
11 #define STATIC_CAST(to, obj) (&(obj)->to##_parent)
14 #define STATIC_UPCAST(to, from, obj) __extension__({ \
15 static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))), \
16 "Invalid upcast object from type"); \
17 (to*)((char*)(obj) - offsetof(to, from##_parent)); \
20 #define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
22 #endif /* __cplusplus */
24 /* Defines method forwards, which call the given parent's (T2's) implementation. */
25 #define DECLARE_FORWARD(T1, T2, rettype, func) \
26 rettype T1##_##func(T1 *obj) \
27 { return T2##_##func(STATIC_CAST(T2, obj)); }
29 #define DECLARE_FORWARD1(T1, T2, rettype, func, argtype1) \
30 rettype T1##_##func(T1 *obj, argtype1 a) \
31 { return T2##_##func(STATIC_CAST(T2, obj), a); }
33 #define DECLARE_FORWARD2(T1, T2, rettype, func, argtype1, argtype2) \
34 rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b) \
35 { return T2##_##func(STATIC_CAST(T2, obj), a, b); }
37 #define DECLARE_FORWARD3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
38 rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b, argtype3 c) \
39 { return T2##_##func(STATIC_CAST(T2, obj), a, b, c); }
41 /* Defines method thunks, functions that call to the child's method. */
42 #define DECLARE_THUNK(T1, T2, rettype, func) \
43 static rettype T1##_##T2##_##func(T2 *obj) \
44 { return T1##_##func(STATIC_UPCAST(T1, T2, obj)); }
46 #define DECLARE_THUNK1(T1, T2, rettype, func, argtype1) \
47 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a) \
48 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a); }
50 #define DECLARE_THUNK2(T1, T2, rettype, func, argtype1, argtype2) \
51 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b) \
52 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b); }
54 #define DECLARE_THUNK3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
55 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
56 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
58 #define DECLARE_THUNK4(T1, T2, rettype, func, argtype1, argtype2, argtype3, argtype4) \
59 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, argtype4 d) \
60 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c, d); }
62 /* Defines the default functions used to (de)allocate a polymorphic object. */
63 #define DECLARE_DEFAULT_ALLOCATORS(T) \
64 static void* T##_New(size_t size) { return al_calloc(16, size); } \
65 static void T##_Delete(void *ptr) { al_free(ptr); }
68 /* Helper to extract an argument list for virtual method calls. */
69 #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
71 /* Call a "virtual" method on an object, with arguments. */
72 #define V(obj, func) ((obj)->vtbl->func((obj), EXTRACT_VCALL_ARGS
73 /* Call a "virtual" method on an object, with no arguments. */
74 #define V0(obj, func) ((obj)->vtbl->func((obj) EXTRACT_VCALL_ARGS
77 /* Helper to extract an argument list for NEW_OBJ calls. */
78 #define EXTRACT_NEW_ARGS(...) __VA_ARGS__); \
82 /* Allocate and construct an object, with arguments. */
83 #define NEW_OBJ(_res, T) do { \
84 _res = (T*)T##_New(sizeof(T)); \
87 T##_Construct(_res, EXTRACT_NEW_ARGS
88 /* Allocate and construct an object, with no arguments. */
89 #define NEW_OBJ0(_res, T) do { \
90 _res = (T*)T##_New(sizeof(T)); \
93 T##_Construct(_res EXTRACT_NEW_ARGS
95 /* Destructs and deallocate an object. */
96 #define DELETE_OBJ(obj) do { \
99 V0((obj),Destruct)(); \
100 V0((obj),Delete)(); \
105 /* Helper to get a type's vtable thunk for a child type. */
106 #define GET_VTABLE2(T1, T2) (&(T1##_##T2##_vtable))
107 /* Helper to set an object's vtable thunk for a child type. Used when constructing an object. */
108 #define SET_VTABLE2(T1, T2, obj) (STATIC_CAST(T2, obj)->vtbl = GET_VTABLE2(T1, T2))
110 #endif /* POLYMORPHISM_H */