summaryrefslogtreecommitdiffstats
blob: 273f7d2bdc1c691ec385047b8e616b81ebb2efba (plain)
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
#ifndef HIPPOMOCKS_H
#define HIPPOMOCKS_H

#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"

#ifndef EXCEPTION_BUFFER_SIZE
#define EXCEPTION_BUFFER_SIZE 65536
#endif

#ifndef VIRT_FUNC_LIMIT 
#define VIRT_FUNC_LIMIT 1024
#elif VIRT_FUNC_LIMIT > 1024
#error Adjust the code to support more than 1024 virtual functions before setting the VIRT_FUNC_LIMIT above 1024
#endif

#ifdef __EDG__
#define FUNCTION_BASE 3
#define FUNCTION_STRIDE 2
#else
#define FUNCTION_BASE 0
#define FUNCTION_STRIDE 1
#endif

#include <list>
#include <map>
#include <memory>
#include <iostream>
#include <sstream>
#include <cstring>

#ifdef _MSC_VER
// these warnings are pointless and huge, and will confuse new users. 
#pragma warning(push)
// If you can't generate an assignment operator the least you can do is shut up.
#pragma warning(disable: 4512)
// Alignment not right in a union?
#pragma warning(disable: 4121)
// Template parameters have the tendency not to change between executions.
#pragma warning(disable: 4127)
// No deprecated warnings on functions that really aren't deprecated at all.
#pragma warning(disable: 4996)
#endif
class MockRepository;

enum RegistrationType {
  Never,
  Once,
  DontCare
};

// base type
class base_mock {
public:
	void destroy() { unwriteVft(); delete this; }
	virtual ~base_mock() {}
	void *rewriteVft(void *newVf) 
	{
		void *oldVf = *(void **)this;
		*(void **)this = newVf;
		return oldVf;
	}
	void unwriteVft() 
	{
		*(void **)this = (*(void ***)this)[-1];
	}
};

class NullType 
{
public: 
	bool operator==(const NullType &) const 
	{
		return true; 
	}
};

struct NotPrintable { template <typename T> NotPrintable(T const&) {} };

inline std::ostream &operator<<(std::ostream &os, NotPrintable const&)
{
	os << "???";
	return os;
}

template <typename T>
struct printArg 
{
  static inline void print(std::ostream &os, T arg, bool withComma)
  {
    if (withComma) os << ",";
    os << arg;
  }
};

template <>
struct printArg<NullType>
{
  static void print(std::ostream &, NullType , bool)
  {
  }
};

class base_tuple 
{
protected:
	base_tuple() 
	{
	} 
public: 
	virtual ~base_tuple() 
	{
	}
	virtual bool operator==(const base_tuple &) const = 0;
  virtual void printTo(std::ostream &os) const = 0;
};

template <typename X>
struct no_cref { typedef X type; };

template <typename X>
struct no_cref<const X &> { typedef X type; };

struct NotComparable { template <typename T> NotComparable(const T&) {} };

inline bool operator==(NotComparable, NotComparable)
{
	return false;
}

template <typename T>
struct comparer
{
  static inline bool compare(T a, T b)
  {
    return a == b;
  }
};

template <typename A = NullType, typename B = NullType, typename C = NullType, typename D = NullType, 
		  typename E = NullType, typename F = NullType, typename G = NullType, typename H = NullType, 
		  typename I = NullType, typename J = NullType, typename K = NullType, typename L = NullType, 
		  typename M = NullType, typename N = NullType, typename O = NullType, typename P = NullType>
class tuple : public base_tuple
{
public:
	typename no_cref<A>::type a;
	typename no_cref<B>::type b;
	typename no_cref<C>::type c;
	typename no_cref<D>::type d;
	typename no_cref<E>::type e;
	typename no_cref<F>::type f;
	typename no_cref<G>::type g;
	typename no_cref<H>::type h;
	typename no_cref<I>::type i;
	typename no_cref<J>::type j;
	typename no_cref<K>::type k;
	typename no_cref<L>::type l;
	typename no_cref<M>::type m;
	typename no_cref<N>::type n;
	typename no_cref<O>::type o;
	typename no_cref<P>::type p;
	tuple(typename no_cref<A>::type a = typename no_cref<A>::type(), typename no_cref<B>::type b = typename no_cref<B>::type(), 
		  typename no_cref<C>::type c = typename no_cref<C>::type(), typename no_cref<D>::type d = typename no_cref<D>::type(), 
		  typename no_cref<E>::type e = typename no_cref<E>::type(), typename no_cref<F>::type f = typename no_cref<F>::type(), 
		  typename no_cref<G>::type g = typename no_cref<G>::type(), typename no_cref<H>::type h = typename no_cref<H>::type(),
		  typename no_cref<I>::type i = typename no_cref<I>::type(), typename no_cref<J>::type j = typename no_cref<J>::type(), 
		  typename no_cref<K>::type k = typename no_cref<K>::type(), typename no_cref<L>::type l = typename no_cref<L>::type(), 
		  typename no_cref<M>::type m = typename no_cref<M>::type(), typename no_cref<N>::type n = typename no_cref<N>::type(), 
		  typename no_cref<O>::type o = typename no_cref<O>::type(), typename no_cref<P>::type p = typename no_cref<P>::type())
		  : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i), j(j), k(k), l(l), m(m), n(n), o(o), p(p)
	{}
	bool operator==(const base_tuple &bo) const {
		const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &to = (const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &)bo;
    return (comparer<A>::compare(a, to.a) &&
            comparer<B>::compare(b, to.b) &&
            comparer<C>::compare(c, to.c) &&
            comparer<D>::compare(d, to.d) &&
            comparer<E>::compare(e, to.e) &&
            comparer<F>::compare(f, to.f) &&
            comparer<G>::compare(g, to.g) &&
            comparer<H>::compare(h, to.h) &&
            comparer<I>::compare(i, to.i) &&
            comparer<J>::compare(j, to.j) &&
            comparer<K>::compare(k, to.k) &&
            comparer<L>::compare(l, to.l) &&
            comparer<M>::compare(m, to.m) &&
            comparer<N>::compare(n, to.n) &&
            comparer<O>::compare(o, to.o) &&
				    comparer<P>::compare(p, to.p));
	}
  virtual void printTo(std::ostream &os) const
  {
    os << "(";
    printArg<A>::print(os, a, false);
    printArg<B>::print(os, b, true);
    printArg<C>::print(os, c, true);
    printArg<D>::print(os, d, true);
    printArg<E>::print(os, e, true);
    printArg<F>::print(os, f, true);
    printArg<G>::print(os, g, true);
    printArg<H>::print(os, h, true);
    printArg<I>::print(os, i, true);
    printArg<J>::print(os, j, true);
    printArg<K>::print(os, k, true);
    printArg<L>::print(os, l, true);
    printArg<M>::print(os, m, true);
    printArg<N>::print(os, n, true);
    printArg<O>::print(os, o, true);
    printArg<P>::print(os, p, true);
    os << ")";
  }
};

class BaseException : public std::exception {
	char buffer[EXCEPTION_BUFFER_SIZE];
public:
	void setException(const char *description, MockRepository *repo);
	const char *what() const throw() { return buffer; }
};

// exception types
class ExpectationException : public BaseException {
public:
  ExpectationException(MockRepository *repo, const base_tuple *tuple, const char *funcName)
  {
  	std::stringstream text;
    text << "Function ";
    text << funcName;
    if (tuple)
      tuple->printTo(text);
    else
      text << "(...)";
    text << " called with mismatching expectation!" << std::endl;
    std::string description = text.str();
    setException(description.c_str(), repo);
  }
};

class NotImplementedException : public BaseException {
public:
	NotImplementedException(MockRepository *repo)
  {
    setException("Function called without expectation!", repo);
  }
};

class CallMissingException : public BaseException {
public:
	CallMissingException(MockRepository *repo)
  {
  	setException("Function with expectation not called!", repo);
  }
};

class NoResultSetUpException : public std::exception {
	char buffer[EXCEPTION_BUFFER_SIZE];
public:
	const char *what() const throw() { return buffer; }
  NoResultSetUpException(const base_tuple *tuple, const char *funcName)
  {
	  std::stringstream text;
    text << "No result set up on call to ";
    text << funcName;
    if (tuple)
      tuple->printTo(text);
    else
      text << "(...)";
    text << std::endl;
	  std::string result = text.str();
	  strncpy(buffer, result.c_str(), sizeof(buffer)-1);
  }
};

// function-index-of-type
class func_index {
public:
	virtual int f0() { return 0; }			virtual int f1() { return 1; }			virtual int f2() { return 2; }			virtual int f3() { return 3; }
	virtual int f4() { return 4; }			virtual int f5() { return 5; }			virtual int f6() { return 6; }			virtual int f7() { return 7; }
	virtual int f8() { return 8; }			virtual int f9() { return 9; }			virtual int f10() { return 10; }		virtual int f11() { return 11; }
	virtual int f12() { return 12; }		virtual int f13() { return 13; }		virtual int f14() { return 14; }		virtual int f15() { return 15; }
	virtual int f16() { return 16; }		virtual int f17() { return 17; }		virtual int f18() { return 18; }		virtual int f19() { return 19; }
	virtual int f20() { return 20; }		virtual int f21() { return 21; }		virtual int f22() { return 22; }		virtual int f23() { return 23; }
	virtual int f24() { return 24; }		virtual int f25() { return 25; }		virtual int f26() { return 26; }		virtual int f27() { return 27; }
	virtual int f28() { return 28; }		virtual int f29() { return 29; }		virtual int f30() { return 30; }		virtual int f31() { return 31; }
	virtual int f32() { return 32; }		virtual int f33() { return 33; }		virtual int f34() { return 34; }		virtual int f35() { return 35; }
	virtual int f36() { return 36; }		virtual int f37() { return 37; }		virtual int f38() { return 38; }		virtual int f39() { return 39; }
	virtual int f40() { return 40; }		virtual int f41() { return 41; }		virtual int f42() { return 42; }		virtual int f43() { return 43; }
	virtual int f44() { return 44; }		virtual int f45() { return 45; }		virtual int f46() { return 46; }		virtual int f47() { return 47; }
	virtual int f48() { return 48; }		virtual int f49() { return 49; }		virtual int f50() { return 50; }		virtual int f51() { return 51; }
	virtual int f52() { return 52; }		virtual int f53() { return 53; }		virtual int f54() { return 54; }		virtual int f55() { return 55; }
	virtual int f56() { return 56; }		virtual int f57() { return 57; }		virtual int f58() { return 58; }		virtual int f59() { return 59; }
	virtual int f60() { return 60; }		virtual int f61() { return 61; }		virtual int f62() { return 62; }		virtual int f63() { return 63; }
	virtual int f64() { return 64; }		virtual int f65() { return 65; }		virtual int f66() { return 66; }		virtual int f67() { return 67; }
	virtual int f68() { return 68; }		virtual int f69() { return 69; }		virtual int f70() { return 70; }		virtual int f71() { return 71; }
	virtual int f72() { return 72; }		virtual int f73() { return 73; }		virtual int f74() { return 74; }		virtual int f75() { return 75; }
	virtual int f76() { return 76; }		virtual int f77() { return 77; }		virtual int f78() { return 78; }		virtual int f79() { return 79; }
	virtual int f80() { return 80; }		virtual int f81() { return 81; }		virtual int f82() { return 82; }		virtual int f83() { return 83; }
	virtual int f84() { return 84; }		virtual int f85() { return 85; }		virtual int f86() { return 86; }		virtual int f87() { return 87; }
	virtual int f88() { return 88; }		virtual int f89() { return 89; }		virtual int f90() { return 90; }		virtual int f91() { return 91; }
	virtual int f92() { return 92; }		virtual int f93() { return 93; }		virtual int f94() { return 94; }		virtual int f95() { return 95; }
	virtual int f96() { return 96; }		virtual int f97() { return 97; }		virtual int f98() { return 98; }		virtual int f99() { return 99; }
	virtual int f100() { return 100; }		virtual int f101() { return 101; }		virtual int f102() { return 102; }		virtual int f103() { return 103; }
	virtual int f104() { return 104; }		virtual int f105() { return 105; }		virtual int f106() { return 106; }		virtual int f107() { return 107; }
	virtual int f108() { return 108; }		virtual int f109() { return 109; }		virtual int f110() { return 110; }		virtual int f111() { return 111; }
	virtual int f112() { return 112; }		virtual int f113() { return 113; }		virtual int f114() { return 114; }		virtual int f115() { return 115; }
	virtual int f116() { return 116; }		virtual int f117() { return 117; }		virtual int f118() { return 118; }		virtual int f119() { return 119; }
	virtual int f120() { return 120; }		virtual int f121() { return 121; }		virtual int f122() { return 122; }		virtual int f123() { return 123; }
	virtual int f124() { return 124; }		virtual int f125() { return 125; }		virtual int f126() { return 126; }		virtual int f127() { return 127; }
	virtual int f128() { return 128; }		virtual int f129() { return 129; }		virtual int f130() { return 130; }		virtual int f131() { return 131; }
	virtual int f132() { return 132; }		virtual int f133() { return 133; }		virtual int f134() { return 134; }		virtual int f135() { return 135; }
	virtual int f136() { return 136; }		virtual int f137() { return 137; }		virtual int f138() { return 138; }		virtual int f139() { return 139; }
	virtual int f140() { return 140; }		virtual int f141() { return 141; }		virtual int f142() { return 142; }		virtual int f143() { return 143; }
	virtual int f144() { return 144; }		virtual int f145() { return 145; }		virtual int f146() { return 146; }		virtual int f147() { return 147; }
	virtual int f148() { return 148; }		virtual int f149() { return 149; }		virtual int f150() { return 150; }		virtual int f151() { return 151; }
	virtual int f152() { return 152; }		virtual int f153() { return 153; }		virtual int f154() { return 154; }		virtual int f155() { return 155; }
	virtual int f156() { return 156; }		virtual int f157() { return 157; }		virtual int f158() { return 158; }		virtual int f159() { return 159; }
	virtual int f160() { return 160; }		virtual int f161() { return 161; }		virtual int f162() { return 162; }		virtual int f163() { return 163; }
	virtual int f164() { return 164; }		virtual int f165() { return 165; }		virtual int f166() { return 166; }		virtual int f167() { return 167; }
	virtual int f168() { return 168; }		virtual int f169() { return 169; }		virtual int f170() { return 170; }		virtual int f171() { return 171; }
	virtual int f172() { return 172; }		virtual int f173() { return 173; }		virtual int f174() { return 174; }		virtual int f175() { return 175; }
	virtual int f176() { return 176; }		virtual int f177() { return 177; }		virtual int f178() { return 178; }		virtual int f179() { return 179; }
	virtual int f180() { return 180; }		virtual int f181() { return 181; }		virtual int f182() { return 182; }		virtual int f183() { return 183; }
	virtual int f184() { return 184; }		virtual int f185() { return 185; }		virtual int f186() { return 186; }		virtual int f187() { return 187; }
	virtual int f188() { return 188; }		virtual int f189() { return 189; }		virtual int f190() { return 190; }		virtual int f191() { return 191; }
	virtual int f192() { return 192; }		virtual int f193() { return 193; }		virtual int f194() { return 194; }		virtual int f195() { return 195; }
	virtual int f196() { return 196; }		virtual int f197() { return 197; }		virtual int f198() { return 198; }		virtual int f199() { return 199; }
	virtual int f200() { return 200; }		virtual int f201() { return 201; }		virtual int f202() { return 202; }		virtual int f203() { return 203; }
	virtual int f204() { return 204; }		virtual int f205() { return 205; }		virtual int f206() { return 206; }		virtual int f207() { return 207; }
	virtual int f208() { return 208; }		virtual int f209() { return 209; }		virtual int f210() { return 210; }		virtual int f211() { return 211; }
	virtual int f212() { return 212; }		virtual int f213() { return 213; }		virtual int f214() { return 214; }		virtual int f215() { return 215; }
	virtual int f216() { return 216; }		virtual int f217() { return 217; }		virtual int f218() { return 218; }		virtual int f219() { return 219; }
	virtual int f220() { return 220; }		virtual int f221() { return 221; }		virtual int f222() { return 222; }		virtual int f223() { return 223; }
	virtual int f224() { return 224; }		virtual int f225() { return 225; }		virtual int f226() { return 226; }		virtual int f227() { return 227; }
	virtual int f228() { return 228; }		virtual int f229() { return 229; }		virtual int f230() { return 230; }		virtual int f231() { return 231; }
	virtual int f232() { return 232; }		virtual int f233() { return 233; }		virtual int f234() { return 234; }		virtual int f235() { return 235; }
	virtual int f236() { return 236; }		virtual int f237() { return 237; }		virtual int f238() { return 238; }		virtual int f239() { return 239; }
	virtual int f240() { return 240; }		virtual int f241() { return 241; }		virtual int f242() { return 242; }		virtual int f243() { return 243; }
	virtual int f244() { return 244; }		virtual int f245() { return 245; }		virtual int f246() { return 246; }		virtual int f247() { return 247; }
	virtual int f248() { return 248; }		virtual int f249() { return 249; }		virtual int f250() { return 250; }		virtual int f251() { return 251; }
	virtual int f252() { return 252; }		virtual int f253() { return 253; }		virtual int f254() { return 254; }		virtual int f255() { return 255; }
	virtual int f256() { return 256; }		virtual int f257() { return 257; }		virtual int f258() { return 258; }		virtual int f259() { return 259; }
	virtual int f260() { return 260; }		virtual int f261() { return 261; }		virtual int f262() { return 262; }		virtual int f263() { return 263; }
	virtual int f264() { return 264; }		virtual int f265() { return 265; }		virtual int f266() { return 266; }		virtual int f267() { return 267; }
	virtual int f268() { return 268; }		virtual int f269() { return 269; }		virtual int f270() { return 270; }		virtual int f271() { return 271; }
	virtual int f272() { return 272; }		virtual int f273() { return 273; }		virtual int f274() { return 274; }		virtual int f275() { return 275; }
	virtual int f276() { return 276; }		virtual int f277() { return 277; }		virtual int f278() { return 278; }		virtual int f279() { return 279; }
	virtual int f280() { return 280; }		virtual int f281() { return 281; }		virtual int f282() { return 282; }		virtual int f283() { return 283; }
	virtual int f284() { return 284; }		virtual int f285() { return 285; }		virtual int f286() { return 286; }		virtual int f287() { return 287; }
	virtual int f288() { return 288; }		virtual int f289() { return 289; }		virtual int f290() { return 290; }		virtual int f291() { return 291; }
	virtual int f292() { return 292; }		virtual int f293() { return 293; }		virtual int f294() { return 294; }		virtual int f295() { return 295; }
	virtual int f296() { return 296; }		virtual int f297() { return 297; }		virtual int f298() { return 298; }		virtual int f299() { return 299; }
	virtual int f300() { return 300; }		virtual int f301() { return 301; }		virtual int f302() { return 302; }		virtual int f303() { return 303; }
	virtual int f304() { return 304; }		virtual int f305() { return 305; }		virtual int f306() { return 306; }		virtual int f307() { return 307; }
	virtual int f308() { return 308; }		virtual int f309() { return 309; }		virtual int f310() { return 310; }		virtual int f311() { return 311; }
	virtual int f312() { return 312; }		virtual int f313() { return 313; }		virtual int f314() { return 314; }		virtual int f315() { return 315; }
	virtual int f316() { return 316; }		virtual int f317() { return 317; }		virtual int f318() { return 318; }		virtual int f319() { return 319; }
	virtual int f320() { return 320; }		virtual int f321() { return 321; }		virtual int f322() { return 322; }		virtual int f323() { return 323; }
	virtual int f324() { return 324; }		virtual int f325() { return 325; }		virtual int f326() { return 326; }		virtual int f327() { return 327; }
	virtual int f328() { return 328; }		virtual int f329() { return 329; }		virtual int f330() { return 330; }		virtual int f331() { return 331; }
	virtual int f332() { return 332; }		virtual int f333() { return 333; }		virtual int f334() { return 334; }		virtual int f335() { return 335; }
	virtual int f336() { return 336; }		virtual int f337() { return 337; }		virtual int f338() { return 338; }		virtual int f339() { return 339; }
	virtual int f340() { return 340; }		virtual int f341() { return 341; }		virtual int f342() { return 342; }		virtual int f343() { return 343; }
	virtual int f344() { return 344; }		virtual int f345() { return 345; }		virtual int f346() { return 346; }		virtual int f347() { return 347; }
	virtual int f348() { return 348; }		virtual int f349() { return 349; }		virtual int f350() { return 350; }		virtual int f351() { return 351; }
	virtual int f352() { return 352; }		virtual int f353() { return 353; }		virtual int f354() { return 354; }		virtual int f355() { return 355; }
	virtual int f356() { return 356; }		virtual int f357() { return 357; }		virtual int f358() { return 358; }		virtual int f359() { return 359; }
	virtual int f360() { return 360; }		virtual int f361() { return 361; }		virtual int f362() { return 362; }		virtual int f363() { return 363; }
	virtual int f364() { return 364; }		virtual int f365() { return 365; }		virtual int f366() { return 366; }		virtual int f367() { return 367; }
	virtual int f368() { return 368; }		virtual int f369() { return 369; }		virtual int f370() { return 370; }		virtual int f371() { return 371; }
	virtual int f372() { return 372; }		virtual int f373() { return 373; }		virtual int f374() { return 374; }		virtual int f375() { return 375; }
	virtual int f376() { return 376; }		virtual int f377() { return 377; }		virtual int f378() { return 378; }		virtual int f379() { return 379; }
	virtual int f380() { return 380; }		virtual int f381() { return 381; }		virtual int f382() { return 382; }		virtual int f383() { return 383; }
	virtual int f384() { return 384; }		virtual int f385() { return 385; }		virtual int f386() { return 386; }		virtual int f387() { return 387; }
	virtual int f388() { return 388; }		virtual int f389() { return 389; }		virtual int f390() { return 390; }		virtual int f391() { return 391; }
	virtual int f392() { return 392; }		virtual int f393() { return 393; }		virtual int f394() { return 394; }		virtual int f395() { return 395; }
	virtual int f396() { return 396; }		virtual int f397() { return 397; }		virtual int f398() { return 398; }		virtual int f399() { return 399; }
	virtual int f400() { return 400; }		virtual int f401() { return 401; }		virtual int f402() { return 402; }		virtual int f403() { return 403; }
	virtual int f404() { return 404; }		virtual int f405() { return 405; }		virtual int f406() { return 406; }		virtual int f407() { return 407; }
	virtual int f408() { return 408; }		virtual int f409() { return 409; }		virtual int f410() { return 410; }		virtual int f411() { return 411; }
	virtual int f412() { return 412; }		virtual int f413() { return 413; }		virtual int f414() { return 414; }		virtual int f415() { return 415; }
	virtual int f416() { return 416; }		virtual int f417() { return 417; }		virtual int f418() { return 418; }		virtual int f419() { return 419; }
	virtual int f420() { return 420; }		virtual int f421() { return 421; }		virtual int f422() { return 422; }		virtual int f423() { return 423; }
	virtual int f424() { return 424; }		virtual int f425() { return 425; }		virtual int f426() { return 426; }		virtual int f427() { return 427; }
	virtual int f428() { return 428; }		virtual int f429() { return 429; }		virtual int f430() { return 430; }		virtual int f431() { return 431; }
	virtual int f432() { return 432; }		virtual int f433() { return 433; }		virtual int f434() { return 434; }		virtual int f435() { return 435; }
	virtual int f436() { return 436; }		virtual int f437() { return 437; }		virtual int f438() { return 438; }		virtual int f439() { return 439; }
	virtual int f440() { return 440; }		virtual int f441() { return 441; }		virtual int f442() { return 442; }		virtual int f443() { return 443; }
	virtual int f444() { return 444; }		virtual int f445() { return 445; }		virtual int f446() { return 446; }		virtual int f447() { return 447; }
	virtual int f448() { return 448; }		virtual int f449() { return 449; }		virtual int f450() { return 450; }		virtual int f451() { return 451; }
	virtual int f452() { return 452; }		virtual int f453() { return 453; }		virtual int f454() { return 454; }		virtual int f455() { return 455; }
	virtual int f456() { return 456; }		virtual int f457() { return 457; }		virtual int f458() { return 458; }		virtual int f459() { return 459; }
	virtual int f460() { return 460; }		virtual int f461() { return 461; }		virtual int f462() { return 462; }		virtual int f463() { return 463; }
	virtual int f464() { return 464; }		virtual int f465() { return 465; }		virtual int f466() { return 466; }		virtual int f467() { return 467; }
	virtual int f468() { return 468; }		virtual int f469() { return 469; }		virtual int f470() { return 470; }		virtual int f471() { return 471; }
	virtual int f472() { return 472; }		virtual int f473() { return 473; }		virtual int f474() { return 474; }		virtual int f475() { return 475; }
	virtual int f476() { return 476; }		virtual int f477() { return 477; }		virtual int f478() { return 478; }		virtual int f479() { return 479; }
	virtual int f480() { return 480; }		virtual int f481() { return 481; }		virtual int f482() { return 482; }		virtual int f483() { return 483; }
	virtual int f484() { return 484; }		virtual int f485() { return 485; }		virtual int f486() { return 486; }		virtual int f487() { return 487; }
	virtual int f488() { return 488; }		virtual int f489() { return 489; }		virtual int f490() { return 490; }		virtual int f491() { return 491; }
	virtual int f492() { return 492; }		virtual int f493() { return 493; }		virtual int f494() { return 494; }		virtual int f495() { return 495; }
	virtual int f496() { return 496; }		virtual int f497() { return 497; }		virtual int f498() { return 498; }		virtual int f499() { return 499; }
	virtual int f500() { return 500; }		virtual int f501() { return 501; }		virtual int f502() { return 502; }		virtual int f503() { return 503; }
	virtual int f504() { return 504; }		virtual int f505() { return 505; }		virtual int f506() { return 506; }		virtual int f507() { return 507; }
	virtual int f508() { return 508; }		virtual int f509() { return 509; }		virtual int f510() { return 510; }		virtual int f511() { return 511; }
	virtual int f512() { return 512; }		virtual int f513() { return 513; }		virtual int f514() { return 514; }		virtual int f515() { return 515; }
	virtual int f516() { return 516; }		virtual int f517() { return 517; }		virtual int f518() { return 518; }		virtual int f519() { return 519; }
	virtual int f520() { return 520; }		virtual int f521() { return 521; }		virtual int f522() { return 522; }		virtual int f523() { return 523; }
	virtual int f524() { return 524; }		virtual int f525() { return 525; }		virtual int f526() { return 526; }		virtual int f527() { return 527; }
	virtual int f528() { return 528; }		virtual int f529() { return 529; }		virtual int f530() { return 530; }		virtual int f531() { return 531; }
	virtual int f532() { return 532; }		virtual int f533() { return 533; }		virtual int f534() { return 534; }		virtual int f535() { return 535; }
	virtual int f536() { return 536; }		virtual int f537() { return 537; }		virtual int f538() { return 538; }		virtual int f539() { return 539; }
	virtual int f540() { return 540; }		virtual int f541() { return 541; }		virtual int f542() { return 542; }		virtual int f543() { return 543; }
	virtual int f544() { return 544; }		virtual int f545() { return 545; }		virtual int f546() { return 546; }		virtual int f547() { return 547; }
	virtual int f548() { return 548; }		virtual int f549() { return 549; }		virtual int f550() { return 550; }		virtual int f551() { return 551; }
	virtual int f552() { return 552; }		virtual int f553() { return 553; }		virtual int f554() { return 554; }		virtual int f555() { return 555; }
	virtual int f556() { return 556; }		virtual int f557() { return 557; }		virtual int f558() { return 558; }		virtual int f559() { return 559; }
	virtual int f560() { return 560; }		virtual int f561() { return 561; }		virtual int f562() { return 562; }		virtual int f563() { return 563; }
	virtual int f564() { return 564; }		virtual int f565() { return 565; }		virtual int f566() { return 566; }		virtual int f567() { return 567; }
	virtual int f568() { return 568; }		virtual int f569() { return 569; }		virtual int f570() { return 570; }		virtual int f571() { return 571; }
	virtual int f572() { return 572; }		virtual int f573() { return 573; }		virtual int f574() { return 574; }		virtual int f575() { return 575; }
	virtual int f576() { return 576; }		virtual int f577() { return 577; }		virtual int f578() { return 578; }		virtual int f579() { return 579; }
	virtual int f580() { return 580; }		virtual int f581() { return 581; }		virtual int f582() { return 582; }		virtual int f583() { return 583; }
	virtual int f584() { return 584; }		virtual int f585() { return 585; }		virtual int f586() { return 586; }		virtual int f587() { return 587; }
	virtual int f588() { return 588; }		virtual int f589() { return 589; }		virtual int f590() { return 590; }		virtual int f591() { return 591; }
	virtual int f592() { return 592; }		virtual int f593() { return 593; }		virtual int f594() { return 594; }		virtual int f595() { return 595; }
	virtual int f596() { return 596; }		virtual int f597() { return 597; }		virtual int f598() { return 598; }		virtual int f599() { return 599; }
	virtual int f600() { return 600; }		virtual int f601() { return 601; }		virtual int f602() { return 602; }		virtual int f603() { return 603; }
	virtual int f604() { return 604; }		virtual int f605() { return 605; }		virtual int f606() { return 606; }		virtual int f607() { return 607; }
	virtual int f608() { return 608; }		virtual int f609() { return 609; }		virtual int f610() { return 610; }		virtual int f611() { return 611; }
	virtual int f612() { return 612; }		virtual int f613() { return 613; }		virtual int f614() { return 614; }		virtual int f615() { return 615; }
	virtual int f616() { return 616; }		virtual int f617() { return 617; }		virtual int f618() { return 618; }		virtual int f619() { return 619; }
	virtual int f620() { return 620; }		virtual int f621() { return 621; }		virtual int f622() { return 622; }		virtual int f623() { return 623; }
	virtual int f624() { return 624; }		virtual int f625() { return 625; }		virtual int f626() { return 626; }		virtual int f627() { return 627; }
	virtual int f628() { return 628; }		virtual int f629() { return 629; }		virtual int f630() { return 630; }		virtual int f631() { return 631; }
	virtual int f632() { return 632; }		virtual int f633() { return 633; }		virtual int f634() { return 634; }		virtual int f635() { return 635; }
	virtual int f636() { return 636; }		virtual int f637() { return 637; }		virtual int f638() { return 638; }		virtual int f639() { return 639; }
	virtual int f640() { return 640; }		virtual int f641() { return 641; }		virtual int f642() { return 642; }		virtual int f643() { return 643; }
	virtual int f644() { return 644; }		virtual int f645() { return 645; }		virtual int f646() { return 646; }		virtual int f647() { return 647; }
	virtual int f648() { return 648; }		virtual int f649() { return 649; }		virtual int f650() { return 650; }		virtual int f651() { return 651; }
	virtual int f652() { return 652; }		virtual int f653() { return 653; }		virtual int f654() { return 654; }		virtual int f655() { return 655; }
	virtual int f656() { return 656; }		virtual int f657() { return 657; }		virtual int f658() { return 658; }		virtual int f659() { return 659; }
	virtual int f660() { return 660; }		virtual int f661() { return 661; }		virtual int f662() { return 662; }		virtual int f663() { return 663; }
	virtual int f664() { return 664; }		virtual int f665() { return 665; }		virtual int f666() { return 666; }		virtual int f667() { return 667; }
	virtual int f668() { return 668; }		virtual int f669() { return 669; }		virtual int f670() { return 670; }		virtual int f671() { return 671; }
	virtual int f672() { return 672; }		virtual int f673() { return 673; }		virtual int f674() { return 674; }		virtual int f675() { return 675; }
	virtual int f676() { return 676; }		virtual int f677() { return 677; }		virtual int f678() { return 678; }		virtual int f679() { return 679; }
	virtual int f680() { return 680; }		virtual int f681() { return 681; }		virtual int f682() { return 682; }		virtual int f683() { return 683; }
	virtual int f684() { return 684; }		virtual int f685() { return 685; }		virtual int f686() { return 686; }		virtual int f687() { return 687; }
	virtual int f688() { return 688; }		virtual int f689() { return 689; }		virtual int f690() { return 690; }		virtual int f691() { return 691; }
	virtual int f692() { return 692; }		virtual int f693() { return 693; }		virtual int f694() { return 694; }		virtual int f695() { return 695; }
	virtual int f696() { return 696; }		virtual int f697() { return 697; }		virtual int f698() { return 698; }		virtual int f699() { return 699; }
	virtual int f700() { return 700; }		virtual int f701() { return 701; }		virtual int f702() { return 702; }		virtual int f703() { return 703; }
	virtual int f704() { return 704; }		virtual int f705() { return 705; }		virtual int f706() { return 706; }		virtual int f707() { return 707; }
	virtual int f708() { return 708; }		virtual int f709() { return 709; }		virtual int f710() { return 710; }		virtual int f711() { return 711; }
	virtual int f712() { return 712; }		virtual int f713() { return 713; }		virtual int f714() { return 714; }		virtual int f715() { return 715; }
	virtual int f716() { return 716; }		virtual int f717() { return 717; }		virtual int f718() { return 718; }		virtual int f719() { return 719; }
	virtual int f720() { return 720; }		virtual int f721() { return 721; }		virtual int f722() { return 722; }		virtual int f723() { return 723; }
	virtual int f724() { return 724; }		virtual int f725() { return 725; }		virtual int f726() { return 726; }		virtual int f727() { return 727; }
	virtual int f728() { return 728; }		virtual int f729() { return 729; }		virtual int f730() { return 730; }		virtual int f731() { return 731; }
	virtual int f732() { return 732; }		virtual int f733() { return 733; }		virtual int f734() { return 734; }		virtual int f735() { return 735; }
	virtual int f736() { return 736; }		virtual int f737() { return 737; }		virtual int f738() { return 738; }		virtual int f739() { return 739; }
	virtual int f740() { return 740; }		virtual int f741() { return 741; }		virtual int f742() { return 742; }		virtual int f743() { return 743; }
	virtual int f744() { return 744; }		virtual int f745() { return 745; }		virtual int f746() { return 746; }		virtual int f747() { return 747; }
	virtual int f748() { return 748; }		virtual int f749() { return 749; }		virtual int f750() { return 750; }		virtual int f751() { return 751; }
	virtual int f752() { return 752; }		virtual int f753() { return 753; }		virtual int f754() { return 754; }		virtual int f755() { return 755; }
	virtual int f756() { return 756; }		virtual int f757() { return 757; }		virtual int f758() { return 758; }		virtual int f759() { return 759; }
	virtual int f760() { return 760; }		virtual int f761() { return 761; }		virtual int f762() { return 762; }		virtual int f763() { return 763; }
	virtual int f764() { return 764; }		virtual int f765() { return 765; }		virtual int f766() { return 766; }		virtual int f767() { return 767; }
	virtual int f768() { return 768; }		virtual int f769() { return 769; }		virtual int f770() { return 770; }		virtual int f771() { return 771; }
	virtual int f772() { return 772; }		virtual int f773() { return 773; }		virtual int f774() { return 774; }		virtual int f775() { return 775; }
	virtual int f776() { return 776; }		virtual int f777() { return 777; }		virtual int f778() { return 778; }		virtual int f779() { return 779; }
	virtual int f780() { return 780; }		virtual int f781() { return 781; }		virtual int f782() { return 782; }		virtual int f783() { return 783; }
	virtual int f784() { return 784; }		virtual int f785() { return 785; }		virtual int f786() { return 786; }		virtual int f787() { return 787; }
	virtual int f788() { return 788; }		virtual int f789() { return 789; }		virtual int f790() { return 790; }		virtual int f791() { return 791; }
	virtual int f792() { return 792; }		virtual int f793() { return 793; }		virtual int f794() { return 794; }		virtual int f795() { return 795; }
	virtual int f796() { return 796; }		virtual int f797() { return 797; }		virtual int f798() { return 798; }		virtual int f799() { return 799; }
	virtual int f800() { return 800; }		virtual int f801() { return 801; }		virtual int f802() { return 802; }		virtual int f803() { return 803; }
	virtual int f804() { return 804; }		virtual int f805() { return 805; }		virtual int f806() { return 806; }		virtual int f807() { return 807; }
	virtual int f808() { return 808; }		virtual int f809() { return 809; }		virtual int f810() { return 810; }		virtual int f811() { return 811; }
	virtual int f812() { return 812; }		virtual int f813() { return 813; }		virtual int f814() { return 814; }		virtual int f815() { return 815; }
	virtual int f816() { return 816; }		virtual int f817() { return 817; }		virtual int f818() { return 818; }		virtual int f819() { return 819; }
	virtual int f820() { return 820; }		virtual int f821() { return 821; }		virtual int f822() { return 822; }		virtual int f823() { return 823; }
	virtual int f824() { return 824; }		virtual int f825() { return 825; }		virtual int f826() { return 826; }		virtual int f827() { return 827; }
	virtual int f828() { return 828; }		virtual int f829() { return 829; }		virtual int f830() { return 830; }		virtual int f831() { return 831; }
	virtual int f832() { return 832; }		virtual int f833() { return 833; }		virtual int f834() { return 834; }		virtual int f835() { return 835; }
	virtual int f836() { return 836; }		virtual int f837() { return 837; }		virtual int f838() { return 838; }		virtual int f839() { return 839; }
	virtual int f840() { return 840; }		virtual int f841() { return 841; }		virtual int f842() { return 842; }		virtual int f843() { return 843; }
	virtual int f844() { return 844; }		virtual int f845() { return 845; }		virtual int f846() { return 846; }		virtual int f847() { return 847; }
	virtual int f848() { return 848; }		virtual int f849() { return 849; }		virtual int f850() { return 850; }		virtual int f851() { return 851; }
	virtual int f852() { return 852; }		virtual int f853() { return 853; }		virtual int f854() { return 854; }		virtual int f855() { return 855; }
	virtual int f856() { return 856; }		virtual int f857() { return 857; }		virtual int f858() { return 858; }		virtual int f859() { return 859; }
	virtual int f860() { return 860; }		virtual int f861() { return 861; }		virtual int f862() { return 862; }		virtual int f863() { return 863; }
	virtual int f864() { return 864; }		virtual int f865() { return 865; }		virtual int f866() { return 866; }		virtual int f867() { return 867; }
	virtual int f868() { return 868; }		virtual int f869() { return 869; }		virtual int f870() { return 870; }		virtual int f871() { return 871; }
	virtual int f872() { return 872; }		virtual int f873() { return 873; }		virtual int f874() { return 874; }		virtual int f875() { return 875; }
	virtual int f876() { return 876; }		virtual int f877() { return 877; }		virtual int f878() { return 878; }		virtual int f879() { return 879; }
	virtual int f880() { return 880; }		virtual int f881() { return 881; }		virtual int f882() { return 882; }		virtual int f883() { return 883; }
	virtual int f884() { return 884; }		virtual int f885() { return 885; }		virtual int f886() { return 886; }		virtual int f887() { return 887; }
	virtual int f888() { return 888; }		virtual int f889() { return 889; }		virtual int f890() { return 890; }		virtual int f891() { return 891; }
	virtual int f892() { return 892; }		virtual int f893() { return 893; }		virtual int f894() { return 894; }		virtual int f895() { return 895; }
	virtual int f896() { return 896; }		virtual int f897() { return 897; }		virtual int f898() { return 898; }		virtual int f899() { return 899; }
	virtual int f900() { return 900; }		virtual int f901() { return 901; }		virtual int f902() { return 902; }		virtual int f903() { return 903; }
	virtual int f904() { return 904; }		virtual int f905() { return 905; }		virtual int f906() { return 906; }		virtual int f907() { return 907; }
	virtual int f908() { return 908; }		virtual int f909() { return 909; }		virtual int f910() { return 910; }		virtual int f911() { return 911; }
	virtual int f912() { return 912; }		virtual int f913() { return 913; }		virtual int f914() { return 914; }		virtual int f915() { return 915; }
	virtual int f916() { return 916; }		virtual int f917() { return 917; }		virtual int f918() { return 918; }		virtual int f919() { return 919; }
	virtual int f920() { return 920; }		virtual int f921() { return 921; }		virtual int f922() { return 922; }		virtual int f923() { return 923; }
	virtual int f924() { return 924; }		virtual int f925() { return 925; }		virtual int f926() { return 926; }		virtual int f927() { return 927; }
	virtual int f928() { return 928; }		virtual int f929() { return 929; }		virtual int f930() { return 930; }		virtual int f931() { return 931; }
	virtual int f932() { return 932; }		virtual int f933() { return 933; }		virtual int f934() { return 934; }		virtual int f935() { return 935; }
	virtual int f936() { return 936; }		virtual int f937() { return 937; }		virtual int f938() { return 938; }		virtual int f939() { return 939; }
	virtual int f940() { return 940; }		virtual int f941() { return 941; }		virtual int f942() { return 942; }		virtual int f943() { return 943; }
	virtual int f944() { return 944; }		virtual int f945() { return 945; }		virtual int f946() { return 946; }		virtual int f947() { return 947; }
	virtual int f948() { return 948; }		virtual int f949() { return 949; }		virtual int f950() { return 950; }		virtual int f951() { return 951; }
	virtual int f952() { return 952; }		virtual int f953() { return 953; }		virtual int f954() { return 954; }		virtual int f955() { return 955; }
	virtual int f956() { return 956; }		virtual int f957() { return 957; }		virtual int f958() { return 958; }		virtual int f959() { return 959; }
	virtual int f960() { return 960; }		virtual int f961() { return 961; }		virtual int f962() { return 962; }		virtual int f963() { return 963; }
	virtual int f964() { return 964; }		virtual int f965() { return 965; }		virtual int f966() { return 966; }		virtual int f967() { return 967; }
	virtual int f968() { return 968; }		virtual int f969() { return 969; }		virtual int f970() { return 970; }		virtual int f971() { return 971; }
	virtual int f972() { return 972; }		virtual int f973() { return 973; }		virtual int f974() { return 974; }		virtual int f975() { return 975; }
	virtual int f976() { return 976; }		virtual int f977() { return 977; }		virtual int f978() { return 978; }		virtual int f979() { return 979; }
	virtual int f980() { return 980; }		virtual int f981() { return 981; }		virtual int f982() { return 982; }		virtual int f983() { return 983; }
	virtual int f984() { return 984; }		virtual int f985() { return 985; }		virtual int f986() { return 986; }		virtual int f987() { return 987; }
	virtual int f988() { return 988; }		virtual int f989() { return 989; }		virtual int f990() { return 990; }		virtual int f991() { return 991; }
	virtual int f992() { return 992; }		virtual int f993() { return 993; }		virtual int f994() { return 994; }		virtual int f995() { return 995; }
	virtual int f996() { return 996; }		virtual int f997() { return 997; }		virtual int f998() { return 998; }		virtual int f999() { return 999; }
	virtual int f1000() { return 1000; }	virtual int f1001() { return 1001; }	virtual int f1002() { return 1002; }	virtual int f1003() { return 1003; }
	virtual int f1004() { return 1004; }	virtual int f1005() { return 1005; }	virtual int f1006() { return 1006; }	virtual int f1007() { return 1007; }
	virtual int f1008() { return 1008; }	virtual int f1009() { return 1009; }	virtual int f1010() { return 1010; }	virtual int f1011() { return 1011; }
	virtual int f1012() { return 1012; }	virtual int f1013() { return 1013; }	virtual int f1014() { return 1014; }	virtual int f1015() { return 1015; }
	virtual int f1016() { return 1016; }	virtual int f1017() { return 1017; }	virtual int f1018() { return 1018; }	virtual int f1019() { return 1019; }
	virtual int f1020() { return 1020; }	virtual int f1021() { return 1021; }	virtual int f1022() { return 1022; }	virtual int f1023() { return 1023; }
	virtual ~func_index() {}
};

template <typename T, typename U>
T getNonvirtualMemberFunctionAddress(U u)
{
#ifdef __EDG__
  // Edison Design Group C++ frontend (Comeau, Portland Group, Greenhills, etc)
  union {
    struct {
      short delta;
      short vindex;
      T t;
    } mfp_structure;
    U u;
  } conv;
#else
  // Visual Studio, GCC, others
  union {
    struct {
      T t;
    } mfp_structure;
    U u;
  } conv;
#endif
  conv.u = u;
  return conv.mfp_structure.t;
}

template <typename T>
int getFunctionIndex(T func) {
	func_index idx;
	return ((&idx)->*reinterpret_cast<int (func_index::*)()>(func))() * FUNCTION_STRIDE + FUNCTION_BASE;
}

// mock types
template <class T>
class mock : public base_mock 
{
	friend class MockRepository;
	unsigned char remaining[sizeof(T)];
	void NotImplemented() { throw NotImplementedException(repo); }
protected:
	void *oldVft;
	void (*funcs[VIRT_FUNC_LIMIT])();
	MockRepository *repo;
public:
	int funcMap[VIRT_FUNC_LIMIT];
	mock(MockRepository *repo) 
		: repo(repo)
	{
		for (int i = 0; i < VIRT_FUNC_LIMIT; i++) 
		{
			funcs[i] = getNonvirtualMemberFunctionAddress<void (*)()>(&mock<T>::NotImplemented);
			funcMap[i] = -1;
		}
		memset(remaining, 0, sizeof(remaining));
		oldVft = base_mock::rewriteVft(funcs);
	}
	int translateX(int x) 
	{
		for (int i = 0; i < VIRT_FUNC_LIMIT; i++) 
		{
			if (funcMap[i] == x) return i;
		}
		return -1;
	}
};

template <class T>
class classMock : public mock<T>
{
	void *backupVft;
public:
	classMock(MockRepository *repo) 
		: mock<T>(repo)
	{
		mock<T>::oldVft = base_mock::rewriteVft((void *)mock<T>::funcs);
		new(this)T();
		backupVft = base_mock::rewriteVft((void *)mock<T>::funcs);
	}
	~classMock()
	{
		base_mock::rewriteVft(backupVft);
		((T *)this)->~T();
	}
};

//Type-safe exception wrapping
class ExceptionHolder 
{ 
public:
	virtual ~ExceptionHolder() {}
	virtual void rethrow() = 0; 
};

template <class T>
class ExceptionWrapper : public ExceptionHolder {
	T exception;
public:
	ExceptionWrapper(T exception) : exception(exception) {}
	void rethrow() { throw exception; }
};

// Do() function wrapping
class VirtualDestructable { public: virtual ~VirtualDestructable() {} };

template <typename Y>
class TupleInvocable : public VirtualDestructable 
{
public:
	virtual Y operator()(const base_tuple &tupl) = 0;
};

template <typename Y,
		  typename A = NullType, typename B = NullType, typename C = NullType, typename D = NullType, 
		  typename E = NullType, typename F = NullType, typename G = NullType, typename H = NullType, 
		  typename I = NullType, typename J = NullType, typename K = NullType, typename L = NullType, 
		  typename M = NullType, typename N = NullType, typename O = NullType, typename P = NullType>
class Invocable : public TupleInvocable<Y>
{
public:
	virtual Y operator()(A a = A(), B b = B(), C c = C(), D d = D(), E e = E(), F f = F(), G g = G(), H h = H(), I i = I(), J j = J(), K k = K(), L l = L(), M m = M(), N n = N(), O o = O(), P p = P()) = 0;
	virtual Y operator()(const base_tuple &tupl) {
		const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &rTupl = reinterpret_cast<const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &>(tupl);
		return (*this)(rTupl.a, rTupl.b, rTupl.c, rTupl.d, rTupl.e, rTupl.f, rTupl.g, rTupl.h, 
			rTupl.i, rTupl.j, rTupl.k, rTupl.l, rTupl.m, rTupl.n, rTupl.o, rTupl.p);
	}
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L, 
		  typename M, typename N, typename O, typename P>
class DoWrapper : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L, 
		  typename M, typename N, typename O>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L, 
		  typename M, typename N>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k,l,m,n);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L, 
		  typename M>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k,l,m);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L,M>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,L,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k,l);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K,L>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J,K> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j,k);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J,K>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H,I,J> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i,j);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I,J>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,NullType,NullType,NullType,NullType,NullType,NullType,NullType>  : public Invocable<Y,A,B,C,D,E,F,G,H,I>{
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, I i, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h,i);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H,I>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H>
class DoWrapper<T,Y,A,B,C,D,E,F,G,H,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G,H> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, H h, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g,h);
	}
	using Invocable<Y,A,B,C,D,E,F,G,H>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G>
class DoWrapper<T,Y,A,B,C,D,E,F,G,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F,G> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, G g, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f,g);
	}
	using Invocable<Y,A,B,C,D,E,F,G>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F>
class DoWrapper<T,Y,A,B,C,D,E,F,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E,F> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, F f, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e,f);
	}
	using Invocable<Y,A,B,C,D,E,F>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D, 
		  typename E>
class DoWrapper<T,Y,A,B,C,D,E,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D,E> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, E e, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d,e);
	}
	using Invocable<Y,A,B,C,D,E>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C, typename D>
class DoWrapper<T,Y,A,B,C,D,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C,D> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, D d, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c,d);
	}
	using Invocable<Y,A,B,C,D>::operator();
};
template <typename T, typename Y,
		  typename A, typename B, typename C>
class DoWrapper<T,Y,A,B,C,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B,C> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, C c, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b,c);
	}
	using Invocable<Y,A,B,C>::operator();
};
template <typename T, typename Y, typename A, typename B>
class DoWrapper<T,Y,A,B,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A,B> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, B b, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a,b);
	}
	using Invocable<Y,A,B>::operator();
};
template <typename T, typename Y, typename A>
class DoWrapper<T,Y,A,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y,A> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(A a, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t(a);
	}
	using Invocable<Y,A>::operator();
};
template <typename T, typename Y>
class DoWrapper<T,Y,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType,NullType> : public Invocable<Y> {
	T &t;
public:
	DoWrapper(T &t) : t(t) {}
	virtual Y operator()(NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType, NullType)
	{
		return t();
	}
	using Invocable<Y>::operator();
};

class ReturnValueHolder {
public:
	virtual ~ReturnValueHolder() {}
};

template <class T>
class ReturnValueWrapper : public ReturnValueHolder {
public:
	typename no_cref<T>::type rv;
	ReturnValueWrapper(T rv) : rv(rv) {}
};

//Call wrapping
class Call {
public:
	virtual bool matchesArgs(const base_tuple &tuple) = 0;
	ReturnValueHolder *retVal;
	ExceptionHolder *eHolder;
	base_mock *mock;
	VirtualDestructable *functor;
	int funcIndex;
	std::list<Call *> previousCalls;
	RegistrationType expectation;
	bool satisfied;
	int lineno;
	const char *funcName;
	const char *fileName;
protected:
	Call(RegistrationType expectation, base_mock *mock, int funcIndex, int X, const char *funcName, const char *fileName) 
		: retVal(0), 
		eHolder(0), 
		mock(mock), 
		functor(0),
		funcIndex(funcIndex), 
		expectation(expectation),
		satisfied(false),
		lineno(X),
		funcName(funcName),
		fileName(fileName)
	{
	}
public:
  virtual const base_tuple *getArgs() const = 0;
	virtual ~Call() 
	{
		delete eHolder;
		delete functor;
		delete retVal;
	}
};

std::ostream &operator<<(std::ostream &os, const Call &call);

template <typename Y, 
		  typename A = NullType, typename B = NullType, typename C = NullType, typename D = NullType, 
		  typename E = NullType, typename F = NullType, typename G = NullType, typename H = NullType, 
		  typename I = NullType, typename J = NullType, typename K = NullType, typename L = NullType, 
		  typename M = NullType, typename N = NullType, typename O = NullType, typename P = NullType>
class TCall : public Call {
private:
	tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> *args;
public:
    const base_tuple *getArgs() const { return args; }
	TCall(RegistrationType expectation, base_mock *mock, int funcIndex, int X, const char *funcName, const char *fileName) : Call(expectation, mock, funcIndex, X, funcName, fileName), args(0) {}
	~TCall() { delete args; }
	bool matchesArgs(const base_tuple &tupl) { return !args || *args == reinterpret_cast<const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &>(tupl); }
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &With(A a = A(), B b = B(), C c = C(), D d = D(), E e = E(), F f = F(), G g = G(), H h = H(), I i = I(), J j = J(), K k = K(), L l = L(), M m = M(), N n = N(), O o = O(), P p = P()) { 
		args = new tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); 
		return *this; 
	}
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &After(Call &call) { 
		previousCalls.push_back(&call);
		return *this; 
	}
	template <typename T>
	Call &Do(T &function) { functor = new DoWrapper<T,Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(function); return *this; }
	Call &Return(Y obj) { retVal = new ReturnValueWrapper<Y>(obj); return *this; }
	template <typename Ex>
	Call &Throw(Ex exception) { eHolder = new ExceptionWrapper<Ex>(exception); return *this; }
};

template <typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H, 
		  typename I, typename J, typename K, typename L, 
		  typename M, typename N, typename O, typename P>
class TCall<void,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> : public Call {
private:
	tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> *args;
public:
  const base_tuple *getArgs() const { return args; }
	TCall(RegistrationType expectation, base_mock *mock, int funcIndex, int X, const char *funcName, const char *fileName) : Call(expectation, mock, funcIndex, X, funcName, fileName), args(0) {}
	~TCall() { delete args; }
	bool matchesArgs(const base_tuple &tupl) { return (!args) || (*args == reinterpret_cast<const tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &>(tupl)); }
	TCall<void,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &With(A a = A(), B b = B(), C c = C(), D d = D(), E e = E(), F f = F(), G g = G(), H h = H(), I i = I(), J j = J(), K k = K(), L l = L(), M m = M(), N n = N(), O o = O(), P p = P()) { 
		args = new tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); 
		return *this; 
	}
	TCall<void,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &After(Call &call) { 
		previousCalls.push_back(&call);
		return *this; 
	}
	template <typename T>
	Call &Do(T &function) { functor = new DoWrapper<T,void,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(function); return *this; }
	template <typename Ex>
	Call &Throw(Ex exception) { eHolder = new ExceptionWrapper<Ex>(exception); return *this; }
};

class MockRepository {
private:
	friend inline std::ostream &operator<<(std::ostream &os, const MockRepository &repo);
	std::list<base_mock *> mocks;
	std::list<Call *> neverCalls;
  std::list<Call *> expectations;
	std::list<Call *> optionals;
public:
	bool autoExpect;
#ifdef _MSC_VER
#define OnCall(obj, func) RegisterExpect_<__COUNTER__, DontCare>(obj, &func, #func, __FILE__, __LINE__)
#define ExpectCall(obj, func) RegisterExpect_<__COUNTER__, Once>(obj, &func, #func, __FILE__, __LINE__)
#define NeverCall(obj, func) RegisterExpect_<__COUNTER__, Never>(obj, &func, #func, __FILE__, __LINE__)
#define OnCallOverload(obj, func) RegisterExpect_<__COUNTER__, DontCare>(obj, func, #func, __FILE__, __LINE__)
#define ExpectCallOverload(obj, func) RegisterExpect_<__COUNTER__, Once>(obj, func, #func, __FILE__, __LINE__)
#define NeverCallOverload(obj, func) RegisterExpect_<__COUNTER__, Never>(obj, func, #func, __FILE__, __LINE__)
#else
#define OnCall(obj, func) RegisterExpect_<__LINE__, DontCare>(obj, &func, #func, __FILE__, __LINE__)
#define ExpectCall(obj, func) RegisterExpect_<__LINE__, Once>(obj, &func, #func, __FILE__, __LINE__)
#define NeverCall(obj, func) RegisterExpect_<__LINE__, Never>(obj, &func, #func, __FILE__, __LINE__)
#define OnCallOverload(obj, func) RegisterExpect_<__LINE__, DontCare>(obj, func, #func, __FILE__, __LINE__)
#define ExpectCallOverload(obj, func) RegisterExpect_<__LINE__, Once>(obj, func, #func, __FILE__, __LINE__)
#define NeverCallOverload(obj, func) RegisterExpect_<__LINE__, Never>(obj, func, #func, __FILE__, __LINE__)
#endif
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z>
	TCall<Y> &RegisterExpect_(Z2 *mck, Y (Z::*func)(), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, typename A>
	TCall<Y,A> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B>
	TCall<Y,A,B> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C>
	TCall<Y,A,B,C> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D>
	TCall<Y,A,B,C,D> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E>
	TCall<Y,A,B,C,D,E> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F>
	TCall<Y,A,B,C,D,E,F> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G>
	TCall<Y,A,B,C,D,E,F,G> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H>
	TCall<Y,A,B,C,D,E,F,G,H> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I>
	TCall<Y,A,B,C,D,E,F,G,H,I> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J>
	TCall<Y,A,B,C,D,E,F,G,H,I,J> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O), const char *funcName, const char *fileName, unsigned long lineNo);
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O, typename P>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P), const char *funcName, const char *fileName, unsigned long lineNo);

	//GCC 3.x doesn't seem to understand overloading on const or non-const member function. Volatile appears to work though.
#if !defined(__GNUC__) || __GNUC__ > 3
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z>
	TCall<Y> &RegisterExpect_(Z2 *mck, Y (Z::*func)() volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)())(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, typename A>
	TCall<Y,A> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B>
	TCall<Y,A,B> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C>
	TCall<Y,A,B,C> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D>
	TCall<Y,A,B,C,D> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E>
	TCall<Y,A,B,C,D,E> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F>
	TCall<Y,A,B,C,D,E,F> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G>
	TCall<Y,A,B,C,D,E,F,G> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H>
	TCall<Y,A,B,C,D,E,F,G,H> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I>
	TCall<Y,A,B,C,D,E,F,G,H,I> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J>
	TCall<Y,A,B,C,D,E,F,G,H,I,J> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O, typename P>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P))(func), funcName, fileName, lineNo); }

	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z>
	TCall<Y> &RegisterExpect_(Z2 *mck, Y (Z::*func)() const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)())(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, typename A>
	TCall<Y,A> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B>
	TCall<Y,A,B> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C>
	TCall<Y,A,B,C> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D>
	TCall<Y,A,B,C,D> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E>
	TCall<Y,A,B,C,D,E> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F>
	TCall<Y,A,B,C,D,E,F> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G>
	TCall<Y,A,B,C,D,E,F,G> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H>
	TCall<Y,A,B,C,D,E,F,G,H> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I>
	TCall<Y,A,B,C,D,E,F,G,H,I> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J>
	TCall<Y,A,B,C,D,E,F,G,H,I,J> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O, typename P>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) const volatile, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P))(func), funcName, fileName, lineNo); }

	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z>
	TCall<Y> &RegisterExpect_(Z2 *mck, Y (Z::*func)() const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)())(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, typename A>
	TCall<Y,A> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B>
	TCall<Y,A,B> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C>
	TCall<Y,A,B,C> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D>
	TCall<Y,A,B,C,D> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E>
	TCall<Y,A,B,C,D,E> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F>
	TCall<Y,A,B,C,D,E,F> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G>
	TCall<Y,A,B,C,D,E,F,G> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H>
	TCall<Y,A,B,C,D,E,F,G,H> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I>
	TCall<Y,A,B,C,D,E,F,G,H,I> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J>
	TCall<Y,A,B,C,D,E,F,G,H,I,J> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O))(func), funcName, fileName, lineNo); }
	template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
			  typename A, typename B, typename C, typename D, 
			  typename E, typename F, typename G, typename H,
			  typename I, typename J, typename K, typename L,
			  typename M, typename N, typename O, typename P>
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) const, const char *funcName, const char *fileName, unsigned long lineNo) { return RegisterExpect_<X,expect>(mck, (Y(Z::*)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P))(func), funcName, fileName, lineNo); }
#endif
	template <typename Z>
	void BasicRegisterExpect(mock<Z> *zMock, int funcIndex, void (base_mock::*func)(), int X);
	template <typename Z>
	Z DoExpectation(base_mock *mock, int funcno, const base_tuple &tuple);
    void DoVoidExpectation(base_mock *mock, int funcno, const base_tuple &tuple) 
    {
		for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end(); ++i) 
		{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno &&
				call->matchesArgs(tuple) &&
				!call->satisfied)
			{
				bool allSatisfy = true;
				for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
					callsBefore != call->previousCalls.end(); ++callsBefore)
				{
					if (!(*callsBefore)->satisfied)
					{
						allSatisfy = false;
					}
				}
				if (!allSatisfy) continue;

				call->satisfied = true;
					
				if (call->eHolder)
					call->eHolder->rethrow();

    			if (call->functor != NULL)
    				(*(TupleInvocable<void> *)(call->functor))(tuple);

				return;
	    	}
		}
		for (std::list<Call *>::iterator i = neverCalls.begin(); i != neverCalls.end(); ++i) 
		{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno &&
				call->matchesArgs(tuple))
			{
				bool allSatisfy = true;
				for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
					callsBefore != call->previousCalls.end(); ++callsBefore)
				{
					if (!(*callsBefore)->satisfied)
					{
						allSatisfy = false;
					}
				}
				if (!allSatisfy) continue;

				call->satisfied = true;

				throw ExpectationException(this, call->getArgs(), call->funcName);
			}
		}
		for (std::list<Call *>::iterator i = optionals.begin(); i != optionals.end(); ++i) 
		{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno &&
				call->matchesArgs(tuple))
			{
				bool allSatisfy = true;
				for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
					callsBefore != call->previousCalls.end(); ++callsBefore)
				{
					if (!(*callsBefore)->satisfied)
					{
						allSatisfy = false;
					}
				}
				if (!allSatisfy) continue;

				call->satisfied = true;

				if (call->eHolder)
					call->eHolder->rethrow();

            	if (call->functor != NULL)
            		(*(TupleInvocable<void> *)(call->functor))(tuple);

        		return;
			}
		}
		const char *funcName = NULL;
  		for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end() && !funcName; ++i) 
	  	{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno)
			funcName = call->funcName;
		}
  		for (std::list<Call *>::iterator i = optionals.begin(); i != optionals.end() && !funcName; ++i) 
		{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno)
			funcName = call->funcName;
		}
  		for (std::list<Call *>::iterator i = neverCalls.begin(); i != neverCalls.end() && !funcName; ++i) 
		{
			Call *call = *i;
			if (call->mock == mock &&
				call->funcIndex == funcno)
            funcName = call->funcName;
	    }
        throw ExpectationException(this, &tuple, funcName);
    }
    MockRepository() 
    	: autoExpect(true)
    {
    }
    ~MockRepository() 
    {
		if (!std::uncaught_exception())
			VerifyAll();
		reset();
		for (std::list<base_mock *>::iterator i = mocks.begin(); i != mocks.end(); i++) 
		{
			(*i)->destroy();
		}
		mocks.clear();
    }
	void reset() 
	{
		for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end(); i++) 
		{
			delete *i;
		}
		expectations.clear();
		for (std::list<Call *>::iterator i = neverCalls.begin(); i != neverCalls.end(); i++) 
		{
			delete *i;
		}
		neverCalls.clear();
		for (std::list<Call *>::iterator i = optionals.begin(); i != optionals.end(); i++) 
		{
			delete *i;
		}
		optionals.clear();
	}
    void VerifyAll() 
	{
		for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end(); i++) 
		{
			if (!(*i)->satisfied)
	    		throw CallMissingException(this);
		}
    }
	template <typename base>
	base *InterfaceMock();
	template <typename base>
	base *ClassMock();
};

// mock function providers
template <typename Z, typename Y>
class mockFuncs : public mock<Z> {
private: 
    mockFuncs();
public:
	template <int X>
	Y expectation0()
	{
        MockRepository *repo = mock<Z>::repo;
        return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<>());
	}
	template <int X, typename A>
	Y expectation1(A a)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A>(a));
	}
	template <int X, typename A, typename B>
	Y expectation2(A a, B b)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B>(a,b));
	}
	template <int X, typename A, typename B, typename C>
	Y expectation3(A a, B b, C c)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C>(a,b,c));
	}
	template <int X, typename A, typename B, typename C, typename D>
	Y expectation4(A a, B b, C c, D d)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D>(a,b,c,d));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E>
	Y expectation5(A a, B b, C c, D d, E e)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E>(a,b,c,d,e));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F>
	Y expectation6(A a, B b, C c, D d, E e, F f)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F>(a,b,c,d,e,f));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G>
	Y expectation7(A a, B b, C c, D d, E e, F f, G g)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G>(a,b,c,d,e,f,g));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
	Y expectation8(A a, B b, C c, D d, E e, F f, G g, H h)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), new tuple<A,B,C,D,E,F,G,H>(a,b,c,d,e,f,g,h));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
	Y expectation9(A a, B b, C c, D d, E e, F f, G g, H h, I i)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I>(a,b,c,d,e,f,g,h,i));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J>
	Y expectation10(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J>(a,b,c,d,e,f,g,h,i,j));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K>
	Y expectation11(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K>(a,b,c,d,e,f,g,h,i,j,k));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L>
	Y expectation12(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L>(a,b,c,d,e,f,g,h,i,j,k,l));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M>
	Y expectation13(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M>(a,b,c,d,e,f,g,h,i,j,k,l,m));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N>
	Y expectation14(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n)
	{
        MockRepository *repo = mock<Z>::repo;
        return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N>(a,b,c,d,e,f,g,h,i,j,k,l,m,n));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O>
	Y expectation15(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O, typename P>
	Y expectation16(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p)
	{
        MockRepository *repo = mock<Z>::repo;
		return repo->template DoExpectation<Y>(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p));
	}
};

template <typename Z>
class mockFuncs<Z, void> : public mock<Z> {
private: 
    mockFuncs();
public:
	template <int X>
	void expectation0()
	{
        MockRepository *repo = mock<Z>::repo;
        repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<>());
	}
	template <int X, typename A>
	void expectation1(A a)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A>(a));
	}
	template <int X, typename A, typename B>
	void expectation2(A a, B b)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B>(a,b));
	}
	template <int X, typename A, typename B, typename C>
	void expectation3(A a, B b, C c)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C>(a,b,c));
	}
	template <int X, typename A, typename B, typename C, typename D>
	void expectation4(A a, B b, C c, D d)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D>(a,b,c,d));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E>
	void expectation5(A a, B b, C c, D d, E e)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E>(a,b,c,d,e));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F>
	void expectation6(A a, B b, C c, D d, E e, F f)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F>(a,b,c,d,e,f));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G>
	void expectation7(A a, B b, C c, D d, E e, F f, G g)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G>(a,b,c,d,e,f,g));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
	void expectation8(A a, B b, C c, D d, E e, F f, G g, H h)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H>(a,b,c,d,e,f,g,h));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
	void expectation9(A a, B b, C c, D d, E e, F f, G g, H h, I i)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I>(a,b,c,d,e,f,g,h,i));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J>
	void expectation10(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J>(a,b,c,d,e,f,g,h,i,j));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K>
	void expectation11(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K>(a,b,c,d,e,f,g,h,i,j,k));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L>
	void expectation12(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L>(a,b,c,d,e,f,g,h,i,j,k,l));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M>
	void expectation13(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M>(a,b,c,d,e,f,g,h,i,j,k,l,m));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N>
	void expectation14(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n)
	{
        MockRepository *repo = mock<Z>::repo;
        repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N>(a,b,c,d,e,f,g,h,i,j,k,l,m,n));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O>
	void expectation15(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o));
	}
	template <int X, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O, typename P>
	void expectation16(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o, P p)
	{
        MockRepository *repo = mock<Z>::repo;
		repo->DoVoidExpectation(this, mock<Z>::translateX(X), tuple<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p));
	}
};

template <typename Z>
void MockRepository::BasicRegisterExpect(mock<Z> *zMock, int funcIndex, void (base_mock::*func)(), int X)
{
	if (zMock->funcMap[funcIndex] == -1)
	{
		zMock->funcs[funcIndex] = getNonvirtualMemberFunctionAddress<void (*)()>(func);
		zMock->funcMap[funcIndex] = X;
	}
}

// Mock repository implementation
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z>
TCall<Y> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)();
	mfp = &mockFuncs<Z2, Y>::template expectation0<X>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex, 
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y> *call = new TCall<Y>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, typename A>
TCall<Y,A> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A);
	mfp = &mockFuncs<Z2, Y>::template expectation1<X,A>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A> *call = new TCall<Y,A>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B>
TCall<Y,A,B> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B);
	mfp = &mockFuncs<Z2, Y>::template expectation2<X,A,B>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B> *call = new TCall<Y,A,B>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C>
TCall<Y,A,B,C> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C);
	mfp = &mockFuncs<Z2, Y>::template expectation3<X,A,B,C>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C> *call = new TCall<Y,A,B,C>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
		break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D>
TCall<Y,A,B,C,D> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D);
	mfp = &mockFuncs<Z2, Y>::template expectation4<X,A,B,C,D>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D> *call = new TCall<Y,A,B,C,D>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E>
TCall<Y,A,B,C,D,E> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E);
	mfp = &mockFuncs<Z2, Y>::template expectation5<X,A,B,C,D,E>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E> *call = new TCall<Y,A,B,C,D,E>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
		break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F>
TCall<Y,A,B,C,D,E,F> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F);
	mfp = &mockFuncs<Z2, Y>::template expectation6<X,A,B,C,D,E,F>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F> *call = new TCall<Y,A,B,C,D,E,F>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
		break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G>
TCall<Y,A,B,C,D,E,F,G> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G);
	mfp = &mockFuncs<Z2, Y>::template expectation7<X,A,B,C,D,E,F,G>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G> *call = new TCall<Y,A,B,C,D,E,F,G>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H>
TCall<Y,A,B,C,D,E,F,G,H> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H);
	mfp = &mockFuncs<Z2, Y>::template expectation8<X,A,B,C,D,E,F,G,H>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H> *call = new TCall<Y,A,B,C,D,E,F,G,H>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I>
TCall<Y,A,B,C,D,E,F,G,H,I> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I);
	mfp = &mockFuncs<Z2, Y>::template expectation9<X,A,B,C,D,E,F,G,H,I>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I> *call = new TCall<Y,A,B,C,D,E,F,G,H,I>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J>
TCall<Y,A,B,C,D,E,F,G,H,I,J> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J);
	mfp = &mockFuncs<Z2, Y>::template expectation10<X,A,B,C,D,E,F,G,H,I,J>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
		break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K);
	mfp = &mockFuncs<Z2, Y>::template expectation11<X,A,B,C,D,E,F,G,H,I,J,K>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K, typename L>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K,L);
	mfp = &mockFuncs<Z2, Y>::template expectation12<X,A,B,C,D,E,F,G,H,I,J,K,L>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K, typename L,
		  typename M>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K,L,M);
	mfp = &mockFuncs<Z2, Y>::template expectation13<X,A,B,C,D,E,F,G,H,I,J,K,L,M>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K, typename L,
		  typename M, typename N>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K,L,M,N);
	mfp = &mockFuncs<Z2, Y>::template expectation14<X,A,B,C,D,E,F,G,H,I,J,K,L,M,N>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex, 
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}
template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K, typename L,
		  typename M, typename N, typename O>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O);
	mfp = &mockFuncs<Z2, Y>::template expectation15<X,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex, 
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}

template <int X, RegistrationType expect, typename Z2, typename Y, typename Z, 
		  typename A, typename B, typename C, typename D, 
		  typename E, typename F, typename G, typename H,
		  typename I, typename J, typename K, typename L,
		  typename M, typename N, typename O, typename P>
TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> &MockRepository::RegisterExpect_(Z2 *mck, Y (Z::*func)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P), const char *funcName, const char *fileName, unsigned long lineNo) 
{
	int funcIndex = getFunctionIndex(func);
	Y (mockFuncs<Z2, Y>::*mfp)(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P);
	mfp = &mockFuncs<Z2, Y>::template expectation16<X,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>;
	BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck), 
						funcIndex,
						reinterpret_cast<void (base_mock::*)()>(mfp),X);
	TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P> *call = new TCall<Y,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P>(expect, reinterpret_cast<base_mock *>(mck), funcIndex, lineNo, funcName, fileName);
	switch(expect)
	{
	case Never: neverCalls.push_back(call); break;
	case DontCare: optionals.push_back(call); break;
	case Once:
		if (autoExpect && expectations.size() > 0) 
		{
			call->previousCalls.push_back(expectations.back());
		}
		expectations.push_back(call);
	    break;
	}
	return *call;
}

template <typename Z>
Z MockRepository::DoExpectation(base_mock *mock, int funcno, const base_tuple &tuple) 
{
	for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end(); ++i) 
	{
		Call *call = *i;
		if (call->mock == mock &&
			call->funcIndex == funcno &&
			call->matchesArgs(tuple) &&
			!call->satisfied)
		{
			bool allSatisfy = true;
			for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
				callsBefore != call->previousCalls.end(); ++callsBefore)
			{
				if (!(*callsBefore)->satisfied)
				{
					allSatisfy = false;
				}
			}
			if (!allSatisfy) continue;

			call->satisfied = true;

			if (call->eHolder)
				call->eHolder->rethrow();

    		if (call->retVal)
				return ((ReturnValueWrapper<Z> *)call->retVal)->rv;

    		if (call->functor != NULL)
    			return (*(TupleInvocable<Z> *)(call->functor))(tuple);

        throw NoResultSetUpException(call->getArgs(), call->funcName);
		}
	}
	for (std::list<Call *>::iterator i = neverCalls.begin(); i != neverCalls.end(); ++i) 
	{
		Call *call = *i;
		if (call->mock == mock &&
			call->funcIndex == funcno &&
			call->matchesArgs(tuple))
		{
			bool allSatisfy = true;
			for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
				callsBefore != call->previousCalls.end(); ++callsBefore)
			{
				if (!(*callsBefore)->satisfied)
				{
					allSatisfy = false;
				}
			}
			if (!allSatisfy) continue;

			call->satisfied = true;

			throw ExpectationException(this, call->getArgs(), call->funcName);
		}
	}
	for (std::list<Call *>::iterator i = optionals.begin(); i != optionals.end(); ++i) 
	{
		Call *call = *i;
		if (call->mock == mock &&
			call->funcIndex == funcno &&
			call->matchesArgs(tuple))
		{
			bool allSatisfy = true;
			for (std::list<Call *>::iterator callsBefore = call->previousCalls.begin();
				callsBefore != call->previousCalls.end(); ++callsBefore)
			{
				if (!(*callsBefore)->satisfied)
				{
					allSatisfy = false;
				}
			}
			if (!allSatisfy) continue;

			call->satisfied = true;
			
			if (call->eHolder)
				call->eHolder->rethrow();

    		if (call->retVal)
				return ((ReturnValueWrapper<Z> *)call->retVal)->rv;
        
        	if (call->functor != NULL)
        		return (*(TupleInvocable<Z> *)(call->functor))(tuple);
        
			throw NoResultSetUpException(call->getArgs(), call->funcName);
		}
	}
	const char *funcName = NULL;
	for (std::list<Call *>::iterator i = expectations.begin(); i != expectations.end() && !funcName; ++i) 
	{
		Call *call = *i;
		if (call->mock == mock &&
			call->funcIndex == funcno)
			funcName = call->funcName;
	}
	for (std::list<Call *>::iterator i = neverCalls.begin(); i != neverCalls.end() && !funcName; ++i) 
    {
	    Call *call = *i;
	    if (call->mock == mock &&
		    call->funcIndex == funcno)
        funcName = call->funcName;
    }
	for (std::list<Call *>::iterator i = optionals.begin(); i != optionals.end() && !funcName; ++i) 
    {
	    Call *call = *i;
	    if (call->mock == mock &&
		    call->funcIndex == funcno)
        funcName = call->funcName;
    }
	throw ExpectationException(this, &tuple, funcName);
}
template <typename base>
base *MockRepository::InterfaceMock() {
	mock<base> *m = new mock<base>(this);
    mocks.push_back(m);
	return reinterpret_cast<base *>(m);
}
template <typename base>
base *MockRepository::ClassMock() {
	classMock<base> *m = new classMock<base>(this);
    mocks.push_back(m);
	return reinterpret_cast<base *>(m);
}

inline std::ostream &operator<<(std::ostream &os, const Call &call)
{
	os << call.fileName << "(" << call.lineno << ") ";
	if (call.expectation == Once)
		os << "Expectation for ";
	else
		os << "Result set for ";

	os << call.funcName;

    if (call.getArgs())
        call.getArgs()->printTo(os);
    else
        os << "(...)";

    os << " on the mock at 0x" << call.mock << " was ";

	if (!call.satisfied)
		os << "not ";

	if (call.expectation == Once)
		os << "satisfied." << std::endl;
	else
		os << "used." << std::endl;

	return os;
}

inline std::ostream &operator<<(std::ostream &os, const MockRepository &repo)
{
	if (repo.expectations.size())
	{
		os << "Expections set:" << std::endl;
		for (std::list<Call *>::const_iterator exp = repo.expectations.begin(); exp != repo.expectations.end(); ++exp)
			os << **exp;
		os << std::endl;
	}

	if (repo.neverCalls.size())
	{
		os << "Functions explicitly expected to not be called:" << std::endl;
		for (std::list<Call *>::const_iterator exp = repo.neverCalls.begin(); exp != repo.neverCalls.end(); ++exp)
			os << **exp;
		os << std::endl;
	}

	if (repo.optionals.size())
	{
		os << "Optional results set up:" << std::endl;
		for (std::list<Call *>::const_iterator exp = repo.optionals.begin(); exp != repo.optionals.end(); ++exp)
			os << **exp;
		os << std::endl;
	}

	return os;
}

inline void BaseException::setException(const char *description, MockRepository *repo) 
{
	std::stringstream text;
	text << description;
	text << *repo;
	std::string result = text.str();
	strncpy(buffer, result.c_str(), sizeof(buffer)-1);
	buffer[sizeof(buffer)-1] = '\0';
}

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif