-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsignature.h
More file actions
258 lines (220 loc) · 8.8 KB
/
signature.h
File metadata and controls
258 lines (220 loc) · 8.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//
// Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is granted without fee,
// provided that the above copyright notice and this permission notice
// appear in all source code copies and supporting documentation. The
// software is provided "as is" without any express or implied
// warranty.
#ifndef FCPP_SIGNATURE_DOT_H
#define FCPP_SIGNATURE_DOT_H
#include "config.h"
#include <functional>
#ifndef FCPP_NO_USE_NAMESPACE
namespace fcpp {
#endif
//////////////////////////////////////////////////////////////////////
// Inheritance detection
// Code based on Andrei Alexandrescu's article:
// http://www.cuj.com/experts/1810/alexandr.html
template <class T, class U>
struct ConversionHelper {
typedef char Small;
struct Big { char dummy[2]; };
static Small Test( const U* );
static Big Test(...);
static const T* MakeT();
};
template <class T, class U>
struct Conversion {
typedef ConversionHelper<T,U> H;
static const int lhs = sizeof(H::Test((T*) H::MakeT()));
static const int rhs = sizeof(typename H::Small);
static const bool exists = (lhs==rhs);
static const bool sameType = false;
};
template <class T>
struct Conversion<T, T> {
static const bool exists = true;
static const bool sameType = true;
};
template <class Derived, class Base>
struct Inherits {
static const bool value =
Conversion<Derived,Base>::exists &&
!Conversion<Base,void>::sameType;
};
//////////////////////////////////////////////////////////////////////
// Here are the classes with "nested typedefs" which just help us use
// our own type system; these classes are just inherited.
//
// Note that although the sigs support a large number of arguments, most
// of the rest of the library only supports functions of 0-3 arguments.
//////////////////////////////////////////////////////////////////////
// Handy helper 'nothing' class.
struct Void {};
// This set names functoid arguments and results
template <class A1, class A2 = Void, class A3 = Void, class A4 = Void,
class A5 = Void, class A6 = Void, class R = Void>
struct FunType {
typedef R ResultType;
typedef A1 Arg1Type;
typedef A2 Arg2Type;
typedef A3 Arg3Type;
typedef A4 Arg4Type;
typedef A5 Arg5Type;
typedef A6 Arg6Type;
};
template <class A1, class A2, class A3, class A4, class A5, class R>
struct FunType<A1, A2, A3, A4, A5, R, Void> {
typedef R ResultType;
typedef A1 Arg1Type;
typedef A2 Arg2Type;
typedef A3 Arg3Type;
typedef A4 Arg4Type;
typedef A5 Arg5Type;
};
template <class A1, class A2, class A3, class A4, class R>
struct FunType<A1, A2, A3, A4, R, Void, Void> {
typedef R ResultType;
typedef A1 Arg1Type;
typedef A2 Arg2Type;
typedef A3 Arg3Type;
typedef A4 Arg4Type;
};
template <class A1, class A2, class A3, class R>
struct FunType<A1, A2, A3, R, Void, Void, Void> {
typedef R ResultType;
typedef A1 Arg1Type;
typedef A2 Arg2Type;
typedef A3 Arg3Type;
};
template <class A1, class A2, class R>
struct FunType<A1, A2, R, Void, Void, Void, Void> {
typedef R ResultType;
typedef A1 Arg1Type;
typedef A2 Arg2Type;
};
template <class A1, class R>
struct FunType<A1, R, Void, Void, Void, Void, Void> {
typedef R ResultType;
typedef A1 Arg1Type;
};
template <class R>
struct FunType<R, Void, Void, Void, Void, Void, Void> {
typedef R ResultType;
};
//////////////////////////////////////////////////////////////////////
// Concrete versions
//////////////////////////////////////////////////////////////////////
// This set is used for monomorphic direct functoids; the type names
// are inherited as-is, and also a template-Sig is defined so that
// monomorphic direct functoids can mix freely with polymorphic functoids
// since the latter require a template-Sig member
template < class A1, class A2 = Void, class A3 = Void, class A4 = Void,
class A5 = Void, class A6 = Void, class R = Void >
struct CFunType : public FunType<A1,A2,A3,A4,A5,A6,R> {
template <class P1, class P2, class P3, class P4, class P5, class P6>
struct Sig : public FunType<A1,A2,A3,A4,A5,A6,R> {};
};
template <class A1, class A2, class A3, class A4, class A5, class R>
struct CFunType<A1, A2, A3, A4, A5, R, Void> :
public FunType<A1,A2,A3,A4,A5,R> {
template <class P1, class P2, class P3, class P4, class P5>
struct Sig : public FunType<A1,A2,A3,A4,A5,R> {};
};
template <class A1, class A2, class A3, class A4, class R>
struct CFunType<A1, A2, A3, A4, R, Void, Void> :
public FunType<A1,A2,A3,A4,R> {
template <class P1, class P2, class P3, class P4>
struct Sig : public FunType<A1,A2,A3,A4,R> {};
};
template <class A1, class A2, class A3, class R>
struct CFunType<A1, A2, A3, R, Void, Void, Void> :
public FunType<A1,A2,A3,R> {
template <class P1, class P2, class P3>
struct Sig : public FunType<A1,A2,A3,R> {};
};
template <class A1, class A2, class R>
struct CFunType<A1, A2, R, Void, Void, Void, Void> :
public FunType<A1,A2,R>, public std::binary_function<A1,A2,R> {
template <class P1, class P2>
struct Sig : public FunType<A1,A2,R> {};
};
template <class A1, class R>
struct CFunType<A1, R, Void, Void, Void, Void, Void> :
public FunType<A1,R>, public std::unary_function<A1,R> {
template <class P1>
struct Sig : public FunType<A1,R> {};
};
struct CallableWithoutArguments {};
struct WrongNumberOfSigArgs {};
template <class R>
struct CFunType<R, Void, Void, Void, Void, Void, Void> :
public CallableWithoutArguments, public FunType<R> {
template <class Dummy1=Void, class Dummy2=Void>
struct Sig : public FunType<WrongNumberOfSigArgs> {};
template <class Dummy>
struct Sig<Void,Dummy> : public FunType<R> {};
};
//////////////////////////////////////////////////////////////////////
// Icky helpers
//////////////////////////////////////////////////////////////////////
// These are strictly unnecessary, but they avoid a bug in the g++
// compiler and also make some things shorter to type.
// RT<T, args> means "return type of T when passed argument types <args>"
template <class T, class A1 = Void, class A2 = Void, class A3 = Void,
class A4 = Void, class A5 = Void, class A6 = Void>
struct RT {
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::ResultType ResultType;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg1Type Arg1Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg2Type Arg2Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg3Type Arg3Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg4Type Arg4Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg5Type Arg5Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5, A6>::Arg6Type Arg6Type;
};
template <class T, class A1, class A2, class A3, class A4, class A5>
struct RT<T, A1, A2, A3, A4, A5, Void> {
typedef typename T::template Sig<A1, A2, A3, A4, A5>::ResultType ResultType;
typedef typename T::template Sig<A1, A2, A3, A4, A5>::Arg1Type Arg1Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5>::Arg2Type Arg2Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5>::Arg3Type Arg3Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5>::Arg4Type Arg4Type;
typedef typename T::template Sig<A1, A2, A3, A4, A5>::Arg5Type Arg5Type;
};
template <class T, class A1, class A2, class A3, class A4>
struct RT<T, A1, A2, A3, A4, Void, Void> {
typedef typename T::template Sig<A1, A2, A3, A4>::ResultType ResultType;
typedef typename T::template Sig<A1, A2, A3, A4>::Arg1Type Arg1Type;
typedef typename T::template Sig<A1, A2, A3, A4>::Arg2Type Arg2Type;
typedef typename T::template Sig<A1, A2, A3, A4>::Arg3Type Arg3Type;
typedef typename T::template Sig<A1, A2, A3, A4>::Arg4Type Arg4Type;
};
template <class T, class A1, class A2, class A3>
struct RT<T, A1, A2, A3, Void, Void, Void> {
typedef typename T::template Sig<A1, A2, A3>::ResultType ResultType;
typedef typename T::template Sig<A1, A2, A3>::Arg1Type Arg1Type;
typedef typename T::template Sig<A1, A2, A3>::Arg2Type Arg2Type;
typedef typename T::template Sig<A1, A2, A3>::Arg3Type Arg3Type;
};
template <class T, class A1, class A2>
struct RT<T, A1, A2, Void, Void, Void, Void> {
typedef typename T::template Sig<A1, A2>::ResultType ResultType;
typedef typename T::template Sig<A1, A2>::Arg1Type Arg1Type;
typedef typename T::template Sig<A1, A2>::Arg2Type Arg2Type;
};
template <class T, class A1>
struct RT<T, A1, Void, Void, Void, Void, Void> {
typedef typename T::template Sig<A1>::ResultType ResultType;
typedef typename T::template Sig<A1>::Arg1Type Arg1Type;
};
template <class T>
struct RT<T, Void, Void, Void, Void, Void, Void> {
typedef typename T::template Sig<>::ResultType ResultType;
};
#ifndef FCPP_NO_USE_NAMESPACE
} // end namespace fcpp
#endif
#endif