ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/callback.pl
(Generate patch)

Comparing gvpe/src/callback.pl (file contents):
Revision 1.10 by pcg, Sun Dec 2 00:54:52 2007 UTC vs.
Revision 1.12 by pcg, Tue Dec 4 17:17:19 2007 UTC

31#ifndef CALLBACK_H__ 31#ifndef CALLBACK_H__
32#define CALLBACK_H__ 32#define CALLBACK_H__
33 33
34#define CALLBACK_H_VERSION 3 34#define CALLBACK_H_VERSION 3
35 35
36template<class signature> 36template<typename signature>
37struct callback_funtype_trait;
38
39template<int arity, class signature>
40struct callback_get_impl; 37struct callback;
41 38
42EOF 39EOF
43 40
44for my $a (0..10) { 41for my $a (0..10) {
45 my $CLASS = join "", map ", class A$_", 1..$a; 42 my $CLASS = join "", map ", class A$_", 1..$a;
46 my $TYPE = join ", ", map "A$_", 1..$a; 43 my $TYPE = join ", ", map "A$_", 1..$a;
47 my $ARG = join ", ", map "a$_", 1..$a; 44 my $ARG = join ", ", map "a$_", 1..$a;
48 my $TYPEARG = join ", ", map "A$_ a$_", 1..$a; 45 my $TYPEARG = join ", ", map "A$_ a$_", 1..$a;
49 my $TYPEDEFS = join " ", map "typedef A$_ arg$_\_type;", 1..$a; 46 my $TYPEDEFS = join " ", map "typedef A$_ arg$_\_type;", 1..$a;
50 my $TYPEvoid = $TYPE ? $TYPE : "void"; 47 my $TYPEvoid = $TYPE ? $TYPE : "void";
48 my $_ARG = $ARG ? ", $ARG" : "";
51 my $_TYPE = $TYPE ? ", $TYPE" : ""; 49 my $_TYPE = $TYPE ? ", $TYPE" : "";
50 my $_TYPEARG = $TYPEARG ? ", $TYPEARG" : "";
52 my $_TTYPE = $a ? join "", map ", typename T::arg$_\_type", 1..$a : ""; 51 my $_TTYPE = $a ? join "", map ", typename T::arg$_\_type", 1..$a : "";
53 52
54 print <<EOF; 53 print <<EOF;
55template<class R$CLASS> 54template<class R$CLASS>
56class callback$a 55struct callback<R ($TYPE)>
57{ 56{
58 struct klass; // it is vital that this is never defined 57 typedef R (*ptr_type)(void *self$_TYPE);
59 58
60 typedef R (klass::*ptr_type)($TYPE); 59private:
61 60
62 klass *o; 61 void *self;
63 R (klass::*m)($TYPE); 62 ptr_type func;
63
64protected:
65
66 template<typename method>
67 struct thunktype;
68
69 template<class klass>
70 struct thunktype<R (klass::*)>
71 {
72 typedef klass K;
73 };
74
75 template<class klass, R (klass::*method)($TYPE)>
76 static R thunk (void *self$_TYPEARG)
77 {
78 klass *obj = static_cast<klass *>(self);
79 return (obj->*method) ($ARG);
80 }
64 81
65public: 82public:
66 template<class O1, class O2> 83 template<class K, R (K::*method)($TYPE)>
67 explicit callback$a (O1 *object, R (O2::*method)($TYPE)) 84 void set (K *object)
68 { 85 {
69 o = reinterpret_cast<klass *>(object); 86 self = object;
70 m = reinterpret_cast<R (klass::*)($TYPE)>(method); 87 func = thunk<K, method>;
71 } 88 }
72 89
73 // this works because a standards-compliant C++ compiler
74 // basically can't help it: it doesn't have the knowledge
75 // required to miscompile (klass is not defined anywhere
76 // and nothing is known about the constructor arguments) :)
77 R call($TYPEARG) const 90 R call ($TYPEARG) const
78 { 91 {
79 return (o->*m) ($ARG); 92 return func (self$_ARG);
80 } 93 }
81 94
82 R operator ()($TYPEARG) const 95 R operator ()($TYPEARG) const
83 { 96 {
84 return call ($ARG); 97 return call ($ARG);
85 } 98 }
86}; 99};
87 100
88template<class R$CLASS>
89struct callback_funtype_trait$a
90{
91 static const int arity = $a;
92 typedef R type ($TYPEvoid);
93 typedef R result_type;
94 $TYPEDEFS
95};
96
97template<class R$CLASS>
98struct callback_funtype_trait<R ($TYPE)> : callback_funtype_trait$a<R$_TYPE>
99{
100};
101
102template<class signature>
103struct callback_get_impl<$a, signature>
104{
105 typedef callback_funtype_trait<signature> T;
106 typedef callback$a<typename T::result_type$_TTYPE> type;
107};
108
109EOF 101EOF
110} 102}
111 103
112print <<EOF 104print <<EOF
113 105
114template<class signature>
115struct callback : callback_get_impl<callback_funtype_trait<signature>::arity, signature>::type
116{
117 typedef typename callback_get_impl<callback_funtype_trait<signature>::arity, signature>::type base_type;
118
119 template<class O, class M>
120 explicit callback (O object, M method)
121 : base_type (object, method)
122 {
123 }
124};
125
126#endif 106#endif
127EOF 107EOF
128 108

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines