]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/Functor.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / Functor.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 //     purpose is hereby granted without fee, provided that the above copyright
9 //     notice appear in all copies and that both that copyright notice and this
10 //     permission notice appear in supporting documentation.
11 // The author or Addison-Wesley Longman make no representations about the
12 //     suitability of this software for any purpose. It is provided "as is"
13 //     without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_FUNCTOR_INC_
16 #define LOKI_FUNCTOR_INC_
17
18 // $Id: Functor.h 750 2006-10-17 19:50:02Z syntheticpp $
19
20
21 #include "Typelist.h"
22 #include "Sequence.h"
23 #include "EmptyType.h"
24 #include "SmallObj.h"
25 #include "TypeTraits.h"
26 #include <typeinfo>
27 #include <memory>
28
29 ///  \defgroup FunctorGroup Function objects
30
31 #ifndef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
32 //#define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
33 #endif
34
35 #ifndef LOKI_FUNCTORS_ARE_COMPARABLE
36 //#define LOKI_FUNCTORS_ARE_COMPARABLE
37 #endif
38
39
40 /// \namespace Loki
41 /// All classes of Loki are in the Loki namespace
42 namespace Loki
43 {
44 ////////////////////////////////////////////////////////////////////////////////
45 // class template FunctorImpl (internal)
46 ////////////////////////////////////////////////////////////////////////////////
47
48 namespace Private
49 {
50 template <typename R, template <class, class> class ThreadingModel>
51 struct FunctorImplBase
52 #ifdef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
53 {
54 #else
55                 :
56         public SmallValueObject<ThreadingModel>
57 {
58         inline FunctorImplBase() :
59                 SmallValueObject<ThreadingModel>() {}
60         inline FunctorImplBase(const FunctorImplBase &) :
61                 SmallValueObject<ThreadingModel>() {}
62 #endif
63
64         typedef R ResultType;
65         typedef FunctorImplBase<R, ThreadingModel> FunctorImplBaseType;
66
67         typedef EmptyType Parm1;
68         typedef EmptyType Parm2;
69         typedef EmptyType Parm3;
70         typedef EmptyType Parm4;
71         typedef EmptyType Parm5;
72         typedef EmptyType Parm6;
73         typedef EmptyType Parm7;
74         typedef EmptyType Parm8;
75         typedef EmptyType Parm9;
76         typedef EmptyType Parm10;
77         typedef EmptyType Parm11;
78         typedef EmptyType Parm12;
79         typedef EmptyType Parm13;
80         typedef EmptyType Parm14;
81         typedef EmptyType Parm15;
82
83
84         virtual ~FunctorImplBase()
85         {}
86
87         virtual FunctorImplBase *DoClone() const = 0;
88
89         template <class U>
90         static U *Clone(U *pObj)
91         {
92                 if (!pObj) return 0;
93                 U *pClone = static_cast<U *>(pObj->DoClone());
94                 assert(typeid(*pClone) == typeid(*pObj));
95                 return pClone;
96         }
97
98
99 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
100
101         virtual bool operator==(const FunctorImplBase &) const = 0;
102
103 #endif
104
105 };
106 }
107
108 ////////////////////////////////////////////////////////////////////////////////
109 // macro LOKI_DEFINE_CLONE_FUNCTORIMPL
110 // Implements the DoClone function for a functor implementation
111 ////////////////////////////////////////////////////////////////////////////////
112
113 #define LOKI_DEFINE_CLONE_FUNCTORIMPL(Cls) \
114     virtual Cls* DoClone() const { return new Cls(*this); }
115
116 ////////////////////////////////////////////////////////////////////////////////
117 // class template FunctorImpl
118 // The base class for a hierarchy of functors. The FunctorImpl class is not used
119 //     directly; rather, the Functor class manages and forwards to a pointer to
120 //     FunctorImpl
121 // You may want to derive your own functors from FunctorImpl.
122 // Specializations of FunctorImpl for up to 15 parameters follow
123 ////////////////////////////////////////////////////////////////////////////////
124
125 template <typename R, class TList,
126          template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
127 class FunctorImpl;
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // class template FunctorImpl
131 // Specialization for 0 (zero) parameters
132 ////////////////////////////////////////////////////////////////////////////////
133
134 template <typename R, template <class, class> class ThreadingModel>
135 class FunctorImpl<R, NullType, ThreadingModel>
136         : public Private::FunctorImplBase<R, ThreadingModel>
137 {
138 public:
139         typedef R ResultType;
140         virtual R operator()() = 0;
141 };
142
143 ////////////////////////////////////////////////////////////////////////////////
144 // class template FunctorImpl
145 // Specialization for 1 parameter
146 ////////////////////////////////////////////////////////////////////////////////
147
148 template <typename R, typename P1, template <class, class> class ThreadingModel>
149 class FunctorImpl<R, Seq<P1>, ThreadingModel>
150         : public Private::FunctorImplBase<R, ThreadingModel>
151 {
152 public:
153         typedef R ResultType;
154         typedef typename TypeTraits<P1>::ParameterType Parm1;
155         virtual R operator()(Parm1) = 0;
156 };
157
158 ////////////////////////////////////////////////////////////////////////////////
159 // class template FunctorImpl
160 // Specialization for 2 parameters
161 ////////////////////////////////////////////////////////////////////////////////
162
163 template <typename R, typename P1, typename P2,
164          template <class, class> class ThreadingModel>
165 class FunctorImpl<R, Seq<P1, P2>, ThreadingModel>
166         : public Private::FunctorImplBase<R, ThreadingModel>
167 {
168 public:
169         typedef R ResultType;
170         typedef typename TypeTraits<P1>::ParameterType Parm1;
171         typedef typename TypeTraits<P2>::ParameterType Parm2;
172         virtual R operator()(Parm1, Parm2) = 0;
173 };
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // class template FunctorImpl
177 // Specialization for 3 parameters
178 ////////////////////////////////////////////////////////////////////////////////
179
180 template <typename R, typename P1, typename P2, typename P3,
181          template <class, class> class ThreadingModel>
182 class FunctorImpl<R, Seq<P1, P2, P3>, ThreadingModel>
183         : public Private::FunctorImplBase<R, ThreadingModel>
184 {
185 public:
186         typedef R ResultType;
187         typedef typename TypeTraits<P1>::ParameterType Parm1;
188         typedef typename TypeTraits<P2>::ParameterType Parm2;
189         typedef typename TypeTraits<P3>::ParameterType Parm3;
190         virtual R operator()(Parm1, Parm2, Parm3) = 0;
191 };
192
193 ////////////////////////////////////////////////////////////////////////////////
194 // class template FunctorImpl
195 // Specialization for 4 parameters
196 ////////////////////////////////////////////////////////////////////////////////
197
198 template <typename R, typename P1, typename P2, typename P3, typename P4,
199          template <class, class> class ThreadingModel>
200 class FunctorImpl<R, Seq<P1, P2, P3, P4>, ThreadingModel>
201         : public Private::FunctorImplBase<R, ThreadingModel>
202 {
203 public:
204         typedef R ResultType;
205         typedef typename TypeTraits<P1>::ParameterType Parm1;
206         typedef typename TypeTraits<P2>::ParameterType Parm2;
207         typedef typename TypeTraits<P3>::ParameterType Parm3;
208         typedef typename TypeTraits<P4>::ParameterType Parm4;
209         virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0;
210 };
211
212 ////////////////////////////////////////////////////////////////////////////////
213 // class template FunctorImpl
214 // Specialization for 5 parameters
215 ////////////////////////////////////////////////////////////////////////////////
216
217 template <typename R, typename P1, typename P2, typename P3, typename P4,
218          typename P5,
219          template <class, class> class ThreadingModel>
220 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5>, ThreadingModel>
221         : public Private::FunctorImplBase<R, ThreadingModel>
222 {
223 public:
224         typedef R ResultType;
225         typedef typename TypeTraits<P1>::ParameterType Parm1;
226         typedef typename TypeTraits<P2>::ParameterType Parm2;
227         typedef typename TypeTraits<P3>::ParameterType Parm3;
228         typedef typename TypeTraits<P4>::ParameterType Parm4;
229         typedef typename TypeTraits<P5>::ParameterType Parm5;
230         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0;
231 };
232
233 ////////////////////////////////////////////////////////////////////////////////
234 // class template FunctorImpl
235 // Specialization for 6 parameters
236 ////////////////////////////////////////////////////////////////////////////////
237
238 template <typename R, typename P1, typename P2, typename P3, typename P4,
239          typename P5, typename P6,
240          template <class, class> class ThreadingModel>
241 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6>, ThreadingModel>
242         : public Private::FunctorImplBase<R, ThreadingModel>
243 {
244 public:
245         typedef R ResultType;
246         typedef typename TypeTraits<P1>::ParameterType Parm1;
247         typedef typename TypeTraits<P2>::ParameterType Parm2;
248         typedef typename TypeTraits<P3>::ParameterType Parm3;
249         typedef typename TypeTraits<P4>::ParameterType Parm4;
250         typedef typename TypeTraits<P5>::ParameterType Parm5;
251         typedef typename TypeTraits<P6>::ParameterType Parm6;
252         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0;
253 };
254
255 ////////////////////////////////////////////////////////////////////////////////
256 // class template FunctorImpl
257 // Specialization for 7 parameters
258 ////////////////////////////////////////////////////////////////////////////////
259
260 template <typename R, typename P1, typename P2, typename P3, typename P4,
261          typename P5, typename P6, typename P7,
262          template <class, class> class ThreadingModel>
263 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7>, ThreadingModel>
264         : public Private::FunctorImplBase<R, ThreadingModel>
265 {
266 public:
267         typedef R ResultType;
268         typedef typename TypeTraits<P1>::ParameterType Parm1;
269         typedef typename TypeTraits<P2>::ParameterType Parm2;
270         typedef typename TypeTraits<P3>::ParameterType Parm3;
271         typedef typename TypeTraits<P4>::ParameterType Parm4;
272         typedef typename TypeTraits<P5>::ParameterType Parm5;
273         typedef typename TypeTraits<P6>::ParameterType Parm6;
274         typedef typename TypeTraits<P7>::ParameterType Parm7;
275         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
276                              Parm7) = 0;
277 };
278
279 ////////////////////////////////////////////////////////////////////////////////
280 // class template FunctorImpl
281 // Specialization for 8 parameters
282 ////////////////////////////////////////////////////////////////////////////////
283
284 template <typename R, typename P1, typename P2, typename P3, typename P4,
285          typename P5, typename P6, typename P7, typename P8,
286          template <class, class> class ThreadingModel>
287 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8>,
288         ThreadingModel>
289         : public Private::FunctorImplBase<R, ThreadingModel>
290 {
291 public:
292         typedef R ResultType;
293         typedef typename TypeTraits<P1>::ParameterType Parm1;
294         typedef typename TypeTraits<P2>::ParameterType Parm2;
295         typedef typename TypeTraits<P3>::ParameterType Parm3;
296         typedef typename TypeTraits<P4>::ParameterType Parm4;
297         typedef typename TypeTraits<P5>::ParameterType Parm5;
298         typedef typename TypeTraits<P6>::ParameterType Parm6;
299         typedef typename TypeTraits<P7>::ParameterType Parm7;
300         typedef typename TypeTraits<P8>::ParameterType Parm8;
301         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
302                              Parm7, Parm8) = 0;
303 };
304
305 ////////////////////////////////////////////////////////////////////////////////
306 // class template FunctorImpl
307 // Specialization for 9 parameters
308 ////////////////////////////////////////////////////////////////////////////////
309
310 template <typename R, typename P1, typename P2, typename P3, typename P4,
311          typename P5, typename P6, typename P7, typename P8, typename P9,
312          template <class, class> class ThreadingModel>
313 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9>,
314         ThreadingModel>
315         : public Private::FunctorImplBase<R, ThreadingModel>
316 {
317 public:
318         typedef R ResultType;
319         typedef typename TypeTraits<P1>::ParameterType Parm1;
320         typedef typename TypeTraits<P2>::ParameterType Parm2;
321         typedef typename TypeTraits<P3>::ParameterType Parm3;
322         typedef typename TypeTraits<P4>::ParameterType Parm4;
323         typedef typename TypeTraits<P5>::ParameterType Parm5;
324         typedef typename TypeTraits<P6>::ParameterType Parm6;
325         typedef typename TypeTraits<P7>::ParameterType Parm7;
326         typedef typename TypeTraits<P8>::ParameterType Parm8;
327         typedef typename TypeTraits<P9>::ParameterType Parm9;
328         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
329                              Parm7, Parm8, Parm9) = 0;
330 };
331
332 ////////////////////////////////////////////////////////////////////////////////
333 // class template FunctorImpl
334 // Specialization for 10 parameters
335 ////////////////////////////////////////////////////////////////////////////////
336
337 template <typename R, typename P1, typename P2, typename P3, typename P4,
338          typename P5, typename P6, typename P7, typename P8, typename P9,
339          typename P10,
340          template <class, class> class ThreadingModel>
341 class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10>,
342         ThreadingModel>
343         : public Private::FunctorImplBase<R, ThreadingModel>
344 {
345 public:
346         typedef R ResultType;
347         typedef typename TypeTraits<P1>::ParameterType Parm1;
348         typedef typename TypeTraits<P2>::ParameterType Parm2;
349         typedef typename TypeTraits<P3>::ParameterType Parm3;
350         typedef typename TypeTraits<P4>::ParameterType Parm4;
351         typedef typename TypeTraits<P5>::ParameterType Parm5;
352         typedef typename TypeTraits<P6>::ParameterType Parm6;
353         typedef typename TypeTraits<P7>::ParameterType Parm7;
354         typedef typename TypeTraits<P8>::ParameterType Parm8;
355         typedef typename TypeTraits<P9>::ParameterType Parm9;
356         typedef typename TypeTraits<P10>::ParameterType Parm10;
357         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
358                              Parm7, Parm8, Parm9, Parm10) = 0;
359 };
360
361 ////////////////////////////////////////////////////////////////////////////////
362 // class template FunctorImpl
363 // Specialization for 11 parameters
364 ////////////////////////////////////////////////////////////////////////////////
365
366 template <typename R, typename P1, typename P2, typename P3, typename P4,
367          typename P5, typename P6, typename P7, typename P8, typename P9,
368          typename P10, typename P11,
369          template <class, class> class ThreadingModel>
370 class FunctorImpl<R,
371         Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11>,
372         ThreadingModel>
373         : public Private::FunctorImplBase<R, ThreadingModel>
374 {
375 public:
376         typedef R ResultType;
377         typedef typename TypeTraits<P1>::ParameterType Parm1;
378         typedef typename TypeTraits<P2>::ParameterType Parm2;
379         typedef typename TypeTraits<P3>::ParameterType Parm3;
380         typedef typename TypeTraits<P4>::ParameterType Parm4;
381         typedef typename TypeTraits<P5>::ParameterType Parm5;
382         typedef typename TypeTraits<P6>::ParameterType Parm6;
383         typedef typename TypeTraits<P7>::ParameterType Parm7;
384         typedef typename TypeTraits<P8>::ParameterType Parm8;
385         typedef typename TypeTraits<P9>::ParameterType Parm9;
386         typedef typename TypeTraits<P10>::ParameterType Parm10;
387         typedef typename TypeTraits<P11>::ParameterType Parm11;
388         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
389                              Parm7, Parm8, Parm9, Parm10, Parm11) = 0;
390 };
391
392 ////////////////////////////////////////////////////////////////////////////////
393 // class template FunctorImpl
394 // Specialization for 12 parameters
395 ////////////////////////////////////////////////////////////////////////////////
396
397 template <typename R, typename P1, typename P2, typename P3, typename P4,
398          typename P5, typename P6, typename P7, typename P8, typename P9,
399          typename P10, typename P11, typename P12,
400          template <class, class> class ThreadingModel>
401 class FunctorImpl<R,
402         Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12>,
403         ThreadingModel>
404         : public Private::FunctorImplBase<R, ThreadingModel>
405 {
406 public:
407         typedef R ResultType;
408         typedef typename TypeTraits<P1>::ParameterType Parm1;
409         typedef typename TypeTraits<P2>::ParameterType Parm2;
410         typedef typename TypeTraits<P3>::ParameterType Parm3;
411         typedef typename TypeTraits<P4>::ParameterType Parm4;
412         typedef typename TypeTraits<P5>::ParameterType Parm5;
413         typedef typename TypeTraits<P6>::ParameterType Parm6;
414         typedef typename TypeTraits<P7>::ParameterType Parm7;
415         typedef typename TypeTraits<P8>::ParameterType Parm8;
416         typedef typename TypeTraits<P9>::ParameterType Parm9;
417         typedef typename TypeTraits<P10>::ParameterType Parm10;
418         typedef typename TypeTraits<P11>::ParameterType Parm11;
419         typedef typename TypeTraits<P12>::ParameterType Parm12;
420         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
421                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0;
422 };
423
424 ////////////////////////////////////////////////////////////////////////////////
425 // class template FunctorImpl
426 // Specialization for 13 parameters
427 ////////////////////////////////////////////////////////////////////////////////
428
429 template <typename R, typename P1, typename P2, typename P3, typename P4,
430          typename P5, typename P6, typename P7, typename P8, typename P9,
431          typename P10, typename P11, typename P12, typename P13,
432          template <class, class> class ThreadingModel>
433 class FunctorImpl<R,
434         Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13>,
435         ThreadingModel>
436         : public Private::FunctorImplBase<R, ThreadingModel>
437 {
438 public:
439         typedef R ResultType;
440         typedef typename TypeTraits<P1>::ParameterType Parm1;
441         typedef typename TypeTraits<P2>::ParameterType Parm2;
442         typedef typename TypeTraits<P3>::ParameterType Parm3;
443         typedef typename TypeTraits<P4>::ParameterType Parm4;
444         typedef typename TypeTraits<P5>::ParameterType Parm5;
445         typedef typename TypeTraits<P6>::ParameterType Parm6;
446         typedef typename TypeTraits<P7>::ParameterType Parm7;
447         typedef typename TypeTraits<P8>::ParameterType Parm8;
448         typedef typename TypeTraits<P9>::ParameterType Parm9;
449         typedef typename TypeTraits<P10>::ParameterType Parm10;
450         typedef typename TypeTraits<P11>::ParameterType Parm11;
451         typedef typename TypeTraits<P12>::ParameterType Parm12;
452         typedef typename TypeTraits<P13>::ParameterType Parm13;
453         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
454                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0;
455 };
456
457 ////////////////////////////////////////////////////////////////////////////////
458 // class template FunctorImpl
459 // Specialization for 14 parameters
460 ////////////////////////////////////////////////////////////////////////////////
461
462 template <typename R, typename P1, typename P2, typename P3, typename P4,
463          typename P5, typename P6, typename P7, typename P8, typename P9,
464          typename P10, typename P11, typename P12, typename P13, typename P14,
465          template <class, class> class ThreadingModel>
466 class FunctorImpl<R,
467         Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
468         P14>,
469         ThreadingModel>
470         : public Private::FunctorImplBase<R, ThreadingModel>
471 {
472 public:
473         typedef R ResultType;
474         typedef typename TypeTraits<P1>::ParameterType Parm1;
475         typedef typename TypeTraits<P2>::ParameterType Parm2;
476         typedef typename TypeTraits<P3>::ParameterType Parm3;
477         typedef typename TypeTraits<P4>::ParameterType Parm4;
478         typedef typename TypeTraits<P5>::ParameterType Parm5;
479         typedef typename TypeTraits<P6>::ParameterType Parm6;
480         typedef typename TypeTraits<P7>::ParameterType Parm7;
481         typedef typename TypeTraits<P8>::ParameterType Parm8;
482         typedef typename TypeTraits<P9>::ParameterType Parm9;
483         typedef typename TypeTraits<P10>::ParameterType Parm10;
484         typedef typename TypeTraits<P11>::ParameterType Parm11;
485         typedef typename TypeTraits<P12>::ParameterType Parm12;
486         typedef typename TypeTraits<P13>::ParameterType Parm13;
487         typedef typename TypeTraits<P14>::ParameterType Parm14;
488         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
489                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0;
490 };
491
492 ////////////////////////////////////////////////////////////////////////////////
493 // class template FunctorImpl
494 // Specialization for 15 parameters
495 ////////////////////////////////////////////////////////////////////////////////
496
497 template <typename R, typename P1, typename P2, typename P3, typename P4,
498          typename P5, typename P6, typename P7, typename P8, typename P9,
499          typename P10, typename P11, typename P12, typename P13, typename P14,
500          typename P15, template <class, class> class ThreadingModel>
501 class FunctorImpl<R,
502         Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
503         P14, P15>,
504         ThreadingModel>
505         : public Private::FunctorImplBase<R, ThreadingModel>
506 {
507 public:
508         typedef R ResultType;
509         typedef typename TypeTraits<P1>::ParameterType Parm1;
510         typedef typename TypeTraits<P2>::ParameterType Parm2;
511         typedef typename TypeTraits<P3>::ParameterType Parm3;
512         typedef typename TypeTraits<P4>::ParameterType Parm4;
513         typedef typename TypeTraits<P5>::ParameterType Parm5;
514         typedef typename TypeTraits<P6>::ParameterType Parm6;
515         typedef typename TypeTraits<P7>::ParameterType Parm7;
516         typedef typename TypeTraits<P8>::ParameterType Parm8;
517         typedef typename TypeTraits<P9>::ParameterType Parm9;
518         typedef typename TypeTraits<P10>::ParameterType Parm10;
519         typedef typename TypeTraits<P11>::ParameterType Parm11;
520         typedef typename TypeTraits<P12>::ParameterType Parm12;
521         typedef typename TypeTraits<P13>::ParameterType Parm13;
522         typedef typename TypeTraits<P14>::ParameterType Parm14;
523         typedef typename TypeTraits<P15>::ParameterType Parm15;
524         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
525                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14,
526                              Parm15) = 0;
527 };
528
529 #ifndef LOKI_DISABLE_TYPELIST_MACROS
530
531 ////////////////////////////////////////////////////////////////////////////////
532 // class template FunctorImpl
533 // Specialization for 1 parameter
534 ////////////////////////////////////////////////////////////////////////////////
535
536 template <typename R, typename P1, template <class, class> class ThreadingModel>
537 class FunctorImpl<R, LOKI_TYPELIST_1(P1), ThreadingModel>
538         : public Private::FunctorImplBase<R, ThreadingModel>
539 {
540 public:
541         typedef R ResultType;
542         typedef typename TypeTraits<P1>::ParameterType Parm1;
543         virtual R operator()(Parm1) = 0;
544 };
545
546 ////////////////////////////////////////////////////////////////////////////////
547 // class template FunctorImpl
548 // Specialization for 2 parameters
549 ////////////////////////////////////////////////////////////////////////////////
550
551 template <typename R, typename P1, typename P2,
552          template <class, class> class ThreadingModel>
553 class FunctorImpl<R, LOKI_TYPELIST_2(P1, P2), ThreadingModel>
554         : public Private::FunctorImplBase<R, ThreadingModel>
555 {
556 public:
557         typedef R ResultType;
558         typedef typename TypeTraits<P1>::ParameterType Parm1;
559         typedef typename TypeTraits<P2>::ParameterType Parm2;
560         virtual R operator()(Parm1, Parm2) = 0;
561 };
562
563 ////////////////////////////////////////////////////////////////////////////////
564 // class template FunctorImpl
565 // Specialization for 3 parameters
566 ////////////////////////////////////////////////////////////////////////////////
567
568 template <typename R, typename P1, typename P2, typename P3,
569          template <class, class> class ThreadingModel>
570 class FunctorImpl<R, LOKI_TYPELIST_3(P1, P2, P3), ThreadingModel>
571         : public Private::FunctorImplBase<R, ThreadingModel>
572 {
573 public:
574         typedef R ResultType;
575         typedef typename TypeTraits<P1>::ParameterType Parm1;
576         typedef typename TypeTraits<P2>::ParameterType Parm2;
577         typedef typename TypeTraits<P3>::ParameterType Parm3;
578         virtual R operator()(Parm1, Parm2, Parm3) = 0;
579 };
580
581 ////////////////////////////////////////////////////////////////////////////////
582 // class template FunctorImpl
583 // Specialization for 4 parameters
584 ////////////////////////////////////////////////////////////////////////////////
585
586 template <typename R, typename P1, typename P2, typename P3, typename P4,
587          template <class, class> class ThreadingModel>
588 class FunctorImpl<R, LOKI_TYPELIST_4(P1, P2, P3, P4), ThreadingModel>
589         : public Private::FunctorImplBase<R, ThreadingModel>
590 {
591 public:
592         typedef R ResultType;
593         typedef typename TypeTraits<P1>::ParameterType Parm1;
594         typedef typename TypeTraits<P2>::ParameterType Parm2;
595         typedef typename TypeTraits<P3>::ParameterType Parm3;
596         typedef typename TypeTraits<P4>::ParameterType Parm4;
597         virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0;
598 };
599
600 ////////////////////////////////////////////////////////////////////////////////
601 // class template FunctorImpl
602 // Specialization for 5 parameters
603 ////////////////////////////////////////////////////////////////////////////////
604
605 template <typename R, typename P1, typename P2, typename P3, typename P4,
606          typename P5,
607          template <class, class> class ThreadingModel>
608 class FunctorImpl<R, LOKI_TYPELIST_5(P1, P2, P3, P4, P5), ThreadingModel>
609         : public Private::FunctorImplBase<R, ThreadingModel>
610 {
611 public:
612         typedef R ResultType;
613         typedef typename TypeTraits<P1>::ParameterType Parm1;
614         typedef typename TypeTraits<P2>::ParameterType Parm2;
615         typedef typename TypeTraits<P3>::ParameterType Parm3;
616         typedef typename TypeTraits<P4>::ParameterType Parm4;
617         typedef typename TypeTraits<P5>::ParameterType Parm5;
618         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0;
619 };
620
621 ////////////////////////////////////////////////////////////////////////////////
622 // class template FunctorImpl
623 // Specialization for 6 parameters
624 ////////////////////////////////////////////////////////////////////////////////
625
626 template <typename R, typename P1, typename P2, typename P3, typename P4,
627          typename P5, typename P6,
628          template <class, class> class ThreadingModel>
629 class FunctorImpl<R, LOKI_TYPELIST_6(P1, P2, P3, P4, P5, P6), ThreadingModel>
630         : public Private::FunctorImplBase<R, ThreadingModel>
631 {
632 public:
633         typedef R ResultType;
634         typedef typename TypeTraits<P1>::ParameterType Parm1;
635         typedef typename TypeTraits<P2>::ParameterType Parm2;
636         typedef typename TypeTraits<P3>::ParameterType Parm3;
637         typedef typename TypeTraits<P4>::ParameterType Parm4;
638         typedef typename TypeTraits<P5>::ParameterType Parm5;
639         typedef typename TypeTraits<P6>::ParameterType Parm6;
640         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0;
641 };
642
643 ////////////////////////////////////////////////////////////////////////////////
644 // class template FunctorImpl
645 // Specialization for 7 parameters
646 ////////////////////////////////////////////////////////////////////////////////
647
648 template <typename R, typename P1, typename P2, typename P3, typename P4,
649          typename P5, typename P6, typename P7,
650          template <class, class> class ThreadingModel>
651 class FunctorImpl<R, LOKI_TYPELIST_7(P1, P2, P3, P4, P5, P6, P7), ThreadingModel>
652         : public Private::FunctorImplBase<R, ThreadingModel>
653 {
654 public:
655         typedef R ResultType;
656         typedef typename TypeTraits<P1>::ParameterType Parm1;
657         typedef typename TypeTraits<P2>::ParameterType Parm2;
658         typedef typename TypeTraits<P3>::ParameterType Parm3;
659         typedef typename TypeTraits<P4>::ParameterType Parm4;
660         typedef typename TypeTraits<P5>::ParameterType Parm5;
661         typedef typename TypeTraits<P6>::ParameterType Parm6;
662         typedef typename TypeTraits<P7>::ParameterType Parm7;
663         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
664                              Parm7) = 0;
665 };
666
667 ////////////////////////////////////////////////////////////////////////////////
668 // class template FunctorImpl
669 // Specialization for 8 parameters
670 ////////////////////////////////////////////////////////////////////////////////
671
672 template <typename R, typename P1, typename P2, typename P3, typename P4,
673          typename P5, typename P6, typename P7, typename P8,
674          template <class, class> class ThreadingModel>
675 class FunctorImpl<R, LOKI_TYPELIST_8(P1, P2, P3, P4, P5, P6, P7, P8),
676         ThreadingModel>
677         : public Private::FunctorImplBase<R, ThreadingModel>
678 {
679 public:
680         typedef R ResultType;
681         typedef typename TypeTraits<P1>::ParameterType Parm1;
682         typedef typename TypeTraits<P2>::ParameterType Parm2;
683         typedef typename TypeTraits<P3>::ParameterType Parm3;
684         typedef typename TypeTraits<P4>::ParameterType Parm4;
685         typedef typename TypeTraits<P5>::ParameterType Parm5;
686         typedef typename TypeTraits<P6>::ParameterType Parm6;
687         typedef typename TypeTraits<P7>::ParameterType Parm7;
688         typedef typename TypeTraits<P8>::ParameterType Parm8;
689         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
690                              Parm7, Parm8) = 0;
691 };
692
693 ////////////////////////////////////////////////////////////////////////////////
694 // class template FunctorImpl
695 // Specialization for 9 parameters
696 ////////////////////////////////////////////////////////////////////////////////
697
698 template <typename R, typename P1, typename P2, typename P3, typename P4,
699          typename P5, typename P6, typename P7, typename P8, typename P9,
700          template <class, class> class ThreadingModel>
701 class FunctorImpl<R, LOKI_TYPELIST_9(P1, P2, P3, P4, P5, P6, P7, P8, P9),
702         ThreadingModel>
703         : public Private::FunctorImplBase<R, ThreadingModel>
704 {
705 public:
706         typedef R ResultType;
707         typedef typename TypeTraits<P1>::ParameterType Parm1;
708         typedef typename TypeTraits<P2>::ParameterType Parm2;
709         typedef typename TypeTraits<P3>::ParameterType Parm3;
710         typedef typename TypeTraits<P4>::ParameterType Parm4;
711         typedef typename TypeTraits<P5>::ParameterType Parm5;
712         typedef typename TypeTraits<P6>::ParameterType Parm6;
713         typedef typename TypeTraits<P7>::ParameterType Parm7;
714         typedef typename TypeTraits<P8>::ParameterType Parm8;
715         typedef typename TypeTraits<P9>::ParameterType Parm9;
716         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
717                              Parm7, Parm8, Parm9) = 0;
718 };
719
720 ////////////////////////////////////////////////////////////////////////////////
721 // class template FunctorImpl
722 // Specialization for 10 parameters
723 ////////////////////////////////////////////////////////////////////////////////
724
725 template <typename R, typename P1, typename P2, typename P3, typename P4,
726          typename P5, typename P6, typename P7, typename P8, typename P9,
727          typename P10,
728          template <class, class> class ThreadingModel>
729 class FunctorImpl<R, LOKI_TYPELIST_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10),
730         ThreadingModel>
731         : public Private::FunctorImplBase<R, ThreadingModel>
732 {
733 public:
734         typedef R ResultType;
735         typedef typename TypeTraits<P1>::ParameterType Parm1;
736         typedef typename TypeTraits<P2>::ParameterType Parm2;
737         typedef typename TypeTraits<P3>::ParameterType Parm3;
738         typedef typename TypeTraits<P4>::ParameterType Parm4;
739         typedef typename TypeTraits<P5>::ParameterType Parm5;
740         typedef typename TypeTraits<P6>::ParameterType Parm6;
741         typedef typename TypeTraits<P7>::ParameterType Parm7;
742         typedef typename TypeTraits<P8>::ParameterType Parm8;
743         typedef typename TypeTraits<P9>::ParameterType Parm9;
744         typedef typename TypeTraits<P10>::ParameterType Parm10;
745         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
746                              Parm7, Parm8, Parm9, Parm10) = 0;
747 };
748
749 ////////////////////////////////////////////////////////////////////////////////
750 // class template FunctorImpl
751 // Specialization for 11 parameters
752 ////////////////////////////////////////////////////////////////////////////////
753
754 template <typename R, typename P1, typename P2, typename P3, typename P4,
755          typename P5, typename P6, typename P7, typename P8, typename P9,
756          typename P10, typename P11,
757          template <class, class> class ThreadingModel>
758 class FunctorImpl<R,
759         LOKI_TYPELIST_11(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11),
760         ThreadingModel>
761         : public Private::FunctorImplBase<R, ThreadingModel>
762 {
763 public:
764         typedef R ResultType;
765         typedef typename TypeTraits<P1>::ParameterType Parm1;
766         typedef typename TypeTraits<P2>::ParameterType Parm2;
767         typedef typename TypeTraits<P3>::ParameterType Parm3;
768         typedef typename TypeTraits<P4>::ParameterType Parm4;
769         typedef typename TypeTraits<P5>::ParameterType Parm5;
770         typedef typename TypeTraits<P6>::ParameterType Parm6;
771         typedef typename TypeTraits<P7>::ParameterType Parm7;
772         typedef typename TypeTraits<P8>::ParameterType Parm8;
773         typedef typename TypeTraits<P9>::ParameterType Parm9;
774         typedef typename TypeTraits<P10>::ParameterType Parm10;
775         typedef typename TypeTraits<P11>::ParameterType Parm11;
776         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
777                              Parm7, Parm8, Parm9, Parm10, Parm11) = 0;
778 };
779
780 ////////////////////////////////////////////////////////////////////////////////
781 // class template FunctorImpl
782 // Specialization for 12 parameters
783 ////////////////////////////////////////////////////////////////////////////////
784
785 template <typename R, typename P1, typename P2, typename P3, typename P4,
786          typename P5, typename P6, typename P7, typename P8, typename P9,
787          typename P10, typename P11, typename P12,
788          template <class, class> class ThreadingModel>
789 class FunctorImpl<R,
790         LOKI_TYPELIST_12(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12),
791         ThreadingModel>
792         : public Private::FunctorImplBase<R, ThreadingModel>
793 {
794 public:
795         typedef R ResultType;
796         typedef typename TypeTraits<P1>::ParameterType Parm1;
797         typedef typename TypeTraits<P2>::ParameterType Parm2;
798         typedef typename TypeTraits<P3>::ParameterType Parm3;
799         typedef typename TypeTraits<P4>::ParameterType Parm4;
800         typedef typename TypeTraits<P5>::ParameterType Parm5;
801         typedef typename TypeTraits<P6>::ParameterType Parm6;
802         typedef typename TypeTraits<P7>::ParameterType Parm7;
803         typedef typename TypeTraits<P8>::ParameterType Parm8;
804         typedef typename TypeTraits<P9>::ParameterType Parm9;
805         typedef typename TypeTraits<P10>::ParameterType Parm10;
806         typedef typename TypeTraits<P11>::ParameterType Parm11;
807         typedef typename TypeTraits<P12>::ParameterType Parm12;
808         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
809                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0;
810 };
811
812 ////////////////////////////////////////////////////////////////////////////////
813 // class template FunctorImpl
814 // Specialization for 13 parameters
815 ////////////////////////////////////////////////////////////////////////////////
816
817 template <typename R, typename P1, typename P2, typename P3, typename P4,
818          typename P5, typename P6, typename P7, typename P8, typename P9,
819          typename P10, typename P11, typename P12, typename P13,
820          template <class, class> class ThreadingModel>
821 class FunctorImpl<R,
822         LOKI_TYPELIST_13(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13),
823         ThreadingModel>
824         : public Private::FunctorImplBase<R, ThreadingModel>
825 {
826 public:
827         typedef R ResultType;
828         typedef typename TypeTraits<P1>::ParameterType Parm1;
829         typedef typename TypeTraits<P2>::ParameterType Parm2;
830         typedef typename TypeTraits<P3>::ParameterType Parm3;
831         typedef typename TypeTraits<P4>::ParameterType Parm4;
832         typedef typename TypeTraits<P5>::ParameterType Parm5;
833         typedef typename TypeTraits<P6>::ParameterType Parm6;
834         typedef typename TypeTraits<P7>::ParameterType Parm7;
835         typedef typename TypeTraits<P8>::ParameterType Parm8;
836         typedef typename TypeTraits<P9>::ParameterType Parm9;
837         typedef typename TypeTraits<P10>::ParameterType Parm10;
838         typedef typename TypeTraits<P11>::ParameterType Parm11;
839         typedef typename TypeTraits<P12>::ParameterType Parm12;
840         typedef typename TypeTraits<P13>::ParameterType Parm13;
841         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
842                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0;
843 };
844
845 ////////////////////////////////////////////////////////////////////////////////
846 // class template FunctorImpl
847 // Specialization for 14 parameters
848 ////////////////////////////////////////////////////////////////////////////////
849
850 template <typename R, typename P1, typename P2, typename P3, typename P4,
851          typename P5, typename P6, typename P7, typename P8, typename P9,
852          typename P10, typename P11, typename P12, typename P13, typename P14,
853          template <class, class> class ThreadingModel>
854 class FunctorImpl<R,
855         LOKI_TYPELIST_14(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
856                          P14),
857         ThreadingModel>
858         : public Private::FunctorImplBase<R, ThreadingModel>
859 {
860 public:
861         typedef R ResultType;
862         typedef typename TypeTraits<P1>::ParameterType Parm1;
863         typedef typename TypeTraits<P2>::ParameterType Parm2;
864         typedef typename TypeTraits<P3>::ParameterType Parm3;
865         typedef typename TypeTraits<P4>::ParameterType Parm4;
866         typedef typename TypeTraits<P5>::ParameterType Parm5;
867         typedef typename TypeTraits<P6>::ParameterType Parm6;
868         typedef typename TypeTraits<P7>::ParameterType Parm7;
869         typedef typename TypeTraits<P8>::ParameterType Parm8;
870         typedef typename TypeTraits<P9>::ParameterType Parm9;
871         typedef typename TypeTraits<P10>::ParameterType Parm10;
872         typedef typename TypeTraits<P11>::ParameterType Parm11;
873         typedef typename TypeTraits<P12>::ParameterType Parm12;
874         typedef typename TypeTraits<P13>::ParameterType Parm13;
875         typedef typename TypeTraits<P14>::ParameterType Parm14;
876         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
877                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0;
878 };
879
880 ////////////////////////////////////////////////////////////////////////////////
881 // class template FunctorImpl
882 // Specialization for 15 parameters
883 ////////////////////////////////////////////////////////////////////////////////
884
885 template <typename R, typename P1, typename P2, typename P3, typename P4,
886          typename P5, typename P6, typename P7, typename P8, typename P9,
887          typename P10, typename P11, typename P12, typename P13, typename P14,
888          typename P15, template <class, class> class ThreadingModel>
889 class FunctorImpl<R,
890         LOKI_TYPELIST_15(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
891                          P14, P15),
892         ThreadingModel>
893         : public Private::FunctorImplBase<R, ThreadingModel>
894 {
895 public:
896         typedef R ResultType;
897         typedef typename TypeTraits<P1>::ParameterType Parm1;
898         typedef typename TypeTraits<P2>::ParameterType Parm2;
899         typedef typename TypeTraits<P3>::ParameterType Parm3;
900         typedef typename TypeTraits<P4>::ParameterType Parm4;
901         typedef typename TypeTraits<P5>::ParameterType Parm5;
902         typedef typename TypeTraits<P6>::ParameterType Parm6;
903         typedef typename TypeTraits<P7>::ParameterType Parm7;
904         typedef typename TypeTraits<P8>::ParameterType Parm8;
905         typedef typename TypeTraits<P9>::ParameterType Parm9;
906         typedef typename TypeTraits<P10>::ParameterType Parm10;
907         typedef typename TypeTraits<P11>::ParameterType Parm11;
908         typedef typename TypeTraits<P12>::ParameterType Parm12;
909         typedef typename TypeTraits<P13>::ParameterType Parm13;
910         typedef typename TypeTraits<P14>::ParameterType Parm14;
911         typedef typename TypeTraits<P15>::ParameterType Parm15;
912         virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
913                              Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14,
914                              Parm15) = 0;
915 };
916
917 #endif //LOKI_DISABLE_TYPELIST_MACROS
918
919 ////////////////////////////////////////////////////////////////////////////////
920 // class template FunctorHandler
921 // Wraps functors and pointers to functions
922 ////////////////////////////////////////////////////////////////////////////////
923
924 template <class ParentFunctor, typename Fun>
925 class FunctorHandler
926         : public ParentFunctor::Impl
927 {
928         typedef typename ParentFunctor::Impl Base;
929
930 public:
931         typedef typename Base::ResultType ResultType;
932         typedef typename Base::Parm1 Parm1;
933         typedef typename Base::Parm2 Parm2;
934         typedef typename Base::Parm3 Parm3;
935         typedef typename Base::Parm4 Parm4;
936         typedef typename Base::Parm5 Parm5;
937         typedef typename Base::Parm6 Parm6;
938         typedef typename Base::Parm7 Parm7;
939         typedef typename Base::Parm8 Parm8;
940         typedef typename Base::Parm9 Parm9;
941         typedef typename Base::Parm10 Parm10;
942         typedef typename Base::Parm11 Parm11;
943         typedef typename Base::Parm12 Parm12;
944         typedef typename Base::Parm13 Parm13;
945         typedef typename Base::Parm14 Parm14;
946         typedef typename Base::Parm15 Parm15;
947
948         FunctorHandler(const Fun &fun) : f_(fun) {}
949
950         LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler)
951
952
953 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
954
955
956         bool operator==(const typename Base::FunctorImplBaseType &rhs) const
957         {
958                 // there is no static information if Functor holds a member function
959                 // or a free function; this is the main difference to tr1::function
960                 if(typeid(*this) != typeid(rhs))
961                         return false; // cannot be equal
962
963                 const FunctorHandler &fh = static_cast<const FunctorHandler &>(rhs);
964                 // if this line gives a compiler error, you are using a function object.
965                 // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
966                 return  f_==fh.f_;
967         }
968 #endif
969         // operator() implementations for up to 15 arguments
970
971         ResultType operator()()
972         {
973                 return f_();
974         }
975
976         ResultType operator()(Parm1 p1)
977         {
978                 return f_(p1);
979         }
980
981         ResultType operator()(Parm1 p1, Parm2 p2)
982         {
983                 return f_(p1, p2);
984         }
985
986         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
987         {
988                 return f_(p1, p2, p3);
989         }
990
991         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
992         {
993                 return f_(p1, p2, p3, p4);
994         }
995
996         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
997         {
998                 return f_(p1, p2, p3, p4, p5);
999         }
1000
1001         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1002                               Parm6 p6)
1003         {
1004                 return f_(p1, p2, p3, p4, p5, p6);
1005         }
1006
1007         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1008                               Parm6 p6, Parm7 p7)
1009         {
1010                 return f_(p1, p2, p3, p4, p5, p6, p7);
1011         }
1012
1013         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1014                               Parm6 p6, Parm7 p7, Parm8 p8)
1015         {
1016                 return f_(p1, p2, p3, p4, p5, p6, p7, p8);
1017         }
1018
1019         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1020                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
1021         {
1022                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9);
1023         }
1024
1025         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1026                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
1027         {
1028                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
1029         }
1030
1031         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1032                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
1033         {
1034                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
1035         }
1036
1037         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1038                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1039                               Parm12 p12)
1040         {
1041                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
1042         }
1043
1044         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1045                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1046                               Parm12 p12, Parm13 p13)
1047         {
1048                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
1049         }
1050
1051         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1052                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1053                               Parm12 p12, Parm13 p13, Parm14 p14)
1054         {
1055                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1056                           p14);
1057         }
1058
1059         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1060                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1061                               Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
1062         {
1063                 return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1064                           p14, p15);
1065         }
1066
1067 private:
1068         Fun f_;
1069 };
1070
1071 ////////////////////////////////////////////////////////////////////////////////
1072 // class template FunctorHandler
1073 // Wraps pointers to member functions
1074 ////////////////////////////////////////////////////////////////////////////////
1075
1076 template <class ParentFunctor, typename PointerToObj,
1077          typename PointerToMemFn>
1078 class MemFunHandler : public ParentFunctor::Impl
1079 {
1080         typedef typename ParentFunctor::Impl Base;
1081
1082 public:
1083         typedef typename Base::ResultType ResultType;
1084         typedef typename Base::Parm1 Parm1;
1085         typedef typename Base::Parm2 Parm2;
1086         typedef typename Base::Parm3 Parm3;
1087         typedef typename Base::Parm4 Parm4;
1088         typedef typename Base::Parm5 Parm5;
1089         typedef typename Base::Parm6 Parm6;
1090         typedef typename Base::Parm7 Parm7;
1091         typedef typename Base::Parm8 Parm8;
1092         typedef typename Base::Parm9 Parm9;
1093         typedef typename Base::Parm10 Parm10;
1094         typedef typename Base::Parm11 Parm11;
1095         typedef typename Base::Parm12 Parm12;
1096         typedef typename Base::Parm13 Parm13;
1097         typedef typename Base::Parm14 Parm14;
1098         typedef typename Base::Parm15 Parm15;
1099
1100         MemFunHandler(const PointerToObj &pObj, PointerToMemFn pMemFn)
1101                 : pObj_(pObj), pMemFn_(pMemFn)
1102         {}
1103
1104         LOKI_DEFINE_CLONE_FUNCTORIMPL(MemFunHandler)
1105
1106
1107 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
1108
1109         bool operator==(const typename Base::FunctorImplBaseType &rhs) const
1110         {
1111                 if(typeid(*this) != typeid(rhs))
1112                         return false; // cannot be equal
1113
1114                 const MemFunHandler &mfh = static_cast<const MemFunHandler &>(rhs);
1115                 // if this line gives a compiler error, you are using a function object.
1116                 // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
1117                 return  pObj_==mfh.pObj_ && pMemFn_==mfh.pMemFn_;
1118         }
1119 #endif
1120
1121         ResultType operator()()
1122         {
1123                 return ((*pObj_).*pMemFn_)();
1124         }
1125
1126         ResultType operator()(Parm1 p1)
1127         {
1128                 return ((*pObj_).*pMemFn_)(p1);
1129         }
1130
1131         ResultType operator()(Parm1 p1, Parm2 p2)
1132         {
1133                 return ((*pObj_).*pMemFn_)(p1, p2);
1134         }
1135
1136         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
1137         {
1138                 return ((*pObj_).*pMemFn_)(p1, p2, p3);
1139         }
1140
1141         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
1142         {
1143                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4);
1144         }
1145
1146         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
1147         {
1148                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5);
1149         }
1150
1151         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1152                               Parm6 p6)
1153         {
1154                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6);
1155         }
1156
1157         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1158                               Parm6 p6, Parm7 p7)
1159         {
1160                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7);
1161         }
1162
1163         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1164                               Parm6 p6, Parm7 p7, Parm8 p8)
1165         {
1166                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8);
1167         }
1168
1169         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1170                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
1171         {
1172                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
1173         }
1174
1175         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1176                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
1177         {
1178                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
1179         }
1180
1181         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1182                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
1183         {
1184                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
1185                                            p11);
1186         }
1187
1188         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1189                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1190                               Parm12 p12)
1191         {
1192                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
1193                                            p11, p12);
1194         }
1195
1196         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1197                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1198                               Parm12 p12, Parm13 p13)
1199         {
1200                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
1201                                            p11, p12, p13);
1202         }
1203
1204         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1205                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1206                               Parm12 p12, Parm13 p13, Parm14 p14)
1207         {
1208                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
1209                                            p11, p12, p13, p14);
1210         }
1211
1212         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1213                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1214                               Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
1215         {
1216                 return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
1217                                            p11, p12, p13, p14, p15);
1218         }
1219
1220 private:
1221         PointerToObj pObj_;
1222         PointerToMemFn pMemFn_;
1223 };
1224
1225 ////////////////////////////////////////////////////////////////////////////////
1226 // TR1 exception
1227 //////////////////////////////////////////////////////////////////////////////////
1228
1229 #ifdef LOKI_ENABLE_FUNCTION
1230
1231 class bad_function_call : public std::runtime_error
1232 {
1233 public:
1234         bad_function_call() : std::runtime_error("bad_function_call in Loki::Functor")
1235         {}
1236 };
1237
1238 #define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL if(empty()) throw bad_function_call();
1239
1240 #else
1241
1242 #define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1243
1244 #endif
1245
1246 ////////////////////////////////////////////////////////////////////////////////
1247 ///  \class Functor
1248 ///
1249 ///  \ingroup FunctorGroup
1250 ///  A generalized functor implementation with value semantics
1251 ///
1252 /// \par Macro: LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
1253 /// Define
1254 /// \code LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT \endcode
1255 /// to avoid static instantiation/delete
1256 /// order problems.
1257 /// It often helps against crashes when using static Functors and multi threading.
1258 /// Defining also removes problems when unloading Dlls which hosts
1259 /// static Functor objects.
1260 ///
1261 /// \par Macro: LOKI_FUNCTORS_ARE_COMPARABLE
1262 /// To enable the operator== define the macro
1263 /// \code LOKI_FUNCTORS_ARE_COMPARABLE \endcode
1264 /// The macro is disabled by default, because it breaks compiling functor
1265 /// objects  which have no operator== implemented, keep in mind when you enable
1266 /// operator==.
1267 ////////////////////////////////////////////////////////////////////////////////
1268 template <typename R = void, class TList = NullType,
1269          template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
1270 class Functor
1271 {
1272 public:
1273         // Handy type definitions for the body type
1274         typedef FunctorImpl<R, TList, ThreadingModel> Impl;
1275         typedef R ResultType;
1276         typedef TList ParmList;
1277         typedef typename Impl::Parm1 Parm1;
1278         typedef typename Impl::Parm2 Parm2;
1279         typedef typename Impl::Parm3 Parm3;
1280         typedef typename Impl::Parm4 Parm4;
1281         typedef typename Impl::Parm5 Parm5;
1282         typedef typename Impl::Parm6 Parm6;
1283         typedef typename Impl::Parm7 Parm7;
1284         typedef typename Impl::Parm8 Parm8;
1285         typedef typename Impl::Parm9 Parm9;
1286         typedef typename Impl::Parm10 Parm10;
1287         typedef typename Impl::Parm11 Parm11;
1288         typedef typename Impl::Parm12 Parm12;
1289         typedef typename Impl::Parm13 Parm13;
1290         typedef typename Impl::Parm14 Parm14;
1291         typedef typename Impl::Parm15 Parm15;
1292
1293         // Member functions
1294
1295         Functor() : spImpl_(0)
1296         {}
1297
1298         Functor(const Functor &rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get()))
1299         {}
1300
1301         Functor(std::auto_ptr<Impl> spImpl) : spImpl_(spImpl)
1302         {}
1303
1304         template <typename Fun>
1305         Functor(Fun fun)
1306                 : spImpl_(new FunctorHandler<Functor, Fun>(fun))
1307         {}
1308
1309         template <class PtrObj, typename MemFn>
1310         Functor(const PtrObj &p, MemFn memFn)
1311                 : spImpl_(new MemFunHandler<Functor, PtrObj, MemFn>(p, memFn))
1312         {}
1313
1314         typedef Impl *(std::auto_ptr<Impl>::*unspecified_bool_type)() const;
1315
1316         operator unspecified_bool_type() const
1317         {
1318                 return spImpl_.get() ? &std::auto_ptr<Impl>::get : 0;
1319         }
1320
1321         Functor &operator=(const Functor &rhs)
1322         {
1323                 Functor copy(rhs);
1324                 // swap auto_ptrs by hand
1325                 Impl *p = spImpl_.release();
1326                 spImpl_.reset(copy.spImpl_.release());
1327                 copy.spImpl_.reset(p);
1328                 return *this;
1329         }
1330
1331 #ifdef LOKI_ENABLE_FUNCTION
1332
1333         bool empty() const
1334         {
1335                 return spImpl_.get() == 0;
1336         }
1337
1338         void clear()
1339         {
1340                 spImpl_.reset(0);
1341         }
1342 #endif
1343
1344 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
1345
1346         bool operator==(const Functor &rhs) const
1347         {
1348                 if(spImpl_.get()==0 && rhs.spImpl_.get()==0)
1349                         return true;
1350                 if(spImpl_.get()!=0 && rhs.spImpl_.get()!=0)
1351                         return *spImpl_.get() == *rhs.spImpl_.get();
1352                 else
1353                         return false;
1354         }
1355
1356         bool operator!=(const Functor &rhs) const
1357         {
1358                 return !(*this==rhs);
1359         }
1360 #endif
1361
1362         // operator() implementations for up to 15 arguments
1363
1364         ResultType operator()() const
1365         {
1366                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1367                 return (*spImpl_)();
1368         }
1369
1370         ResultType operator()(Parm1 p1) const
1371         {
1372                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1373                 return (*spImpl_)(p1);
1374         }
1375
1376         ResultType operator()(Parm1 p1, Parm2 p2) const
1377         {
1378                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1379                 return (*spImpl_)(p1, p2);
1380         }
1381
1382         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const
1383         {
1384                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1385                 return (*spImpl_)(p1, p2, p3);
1386         }
1387
1388         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const
1389         {
1390                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1391                 return (*spImpl_)(p1, p2, p3, p4);
1392         }
1393
1394         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const
1395         {
1396                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1397                 return (*spImpl_)(p1, p2, p3, p4, p5);
1398         }
1399
1400         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1401                               Parm6 p6) const
1402         {
1403                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1404                 return (*spImpl_)(p1, p2, p3, p4, p5, p6);
1405         }
1406
1407         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1408                               Parm6 p6, Parm7 p7) const
1409         {
1410                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1411                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7);
1412         }
1413
1414         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1415                               Parm6 p6, Parm7 p7, Parm8 p8) const
1416         {
1417                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1418                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8);
1419         }
1420
1421         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1422                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) const
1423         {
1424                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1425                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
1426         }
1427
1428         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1429                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) const
1430         {
1431                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1432                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
1433         }
1434
1435         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1436                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) const
1437         {
1438                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1439                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
1440         }
1441
1442         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1443                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1444                               Parm12 p12) const
1445         {
1446                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1447                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
1448                                   p12);
1449         }
1450
1451         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1452                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1453                               Parm12 p12, Parm13 p13) const
1454         {
1455                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1456                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
1457                                   p12, p13);
1458         }
1459
1460         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1461                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1462                               Parm12 p12, Parm13 p13, Parm14 p14) const
1463         {
1464                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1465                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
1466                                   p12, p13, p14);
1467         }
1468
1469         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1470                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1471                               Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) const
1472         {
1473                 LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
1474                 return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
1475                                   p12, p13, p14, p15);
1476         }
1477
1478 private:
1479         std::auto_ptr<Impl> spImpl_;
1480 };
1481
1482
1483 ////////////////////////////////////////////////////////////////////////////////
1484 //
1485 //  BindersFirst and Chainer
1486 //
1487 ////////////////////////////////////////////////////////////////////////////////
1488
1489 namespace Private
1490 {
1491 template <class Fctor> struct BinderFirstTraits;
1492
1493 template <typename R, class TList, template <class, class> class ThreadingModel>
1494 struct BinderFirstTraits< Functor<R, TList, ThreadingModel> >
1495 {
1496         typedef Functor<R, TList, ThreadingModel> OriginalFunctor;
1497
1498         typedef typename TL::Erase<TList,typename TL::TypeAt<TList, 0>::Result>
1499         ::Result
1500         ParmList;
1501
1502         typedef typename TL::TypeAt<TList, 0>::Result OriginalParm1;
1503
1504         typedef Functor<R, ParmList, ThreadingModel> BoundFunctorType;
1505
1506         typedef typename BoundFunctorType::Impl Impl;
1507
1508 };
1509
1510
1511 template<class T>
1512 struct BinderFirstBoundTypeStorage;
1513
1514 template<class T>
1515 struct BinderFirstBoundTypeStorage
1516 {
1517         typedef typename TypeTraits<T>::ParameterType RefOrValue;
1518 };
1519
1520 template <typename R, class TList, template <class, class> class ThreadingModel>
1521 struct BinderFirstBoundTypeStorage< Functor<R, TList, ThreadingModel> >
1522 {
1523         typedef Functor<R, TList, ThreadingModel> OriginalFunctor;
1524         typedef const typename TypeTraits<OriginalFunctor>::ReferredType RefOrValue;
1525 };
1526
1527
1528 } // namespace Private
1529
1530 ////////////////////////////////////////////////////////////////////////////////
1531 ///  \class BinderFirst
1532 ///
1533 ///  \ingroup FunctorGroup
1534 ///  Binds the first parameter of a Functor object to a specific value
1535 ////////////////////////////////////////////////////////////////////////////////
1536
1537 template <class OriginalFunctor>
1538 class BinderFirst
1539         : public Private::BinderFirstTraits<OriginalFunctor>::Impl
1540 {
1541         typedef typename Private::BinderFirstTraits<OriginalFunctor>::Impl Base;
1542         typedef typename OriginalFunctor::ResultType ResultType;
1543
1544         typedef typename OriginalFunctor::Parm1 BoundType;
1545
1546         typedef typename Private::BinderFirstBoundTypeStorage<
1547         typename Private::BinderFirstTraits<OriginalFunctor>
1548         ::OriginalParm1>
1549         ::RefOrValue
1550         BoundTypeStorage;
1551
1552         typedef typename OriginalFunctor::Parm2 Parm1;
1553         typedef typename OriginalFunctor::Parm3 Parm2;
1554         typedef typename OriginalFunctor::Parm4 Parm3;
1555         typedef typename OriginalFunctor::Parm5 Parm4;
1556         typedef typename OriginalFunctor::Parm6 Parm5;
1557         typedef typename OriginalFunctor::Parm7 Parm6;
1558         typedef typename OriginalFunctor::Parm8 Parm7;
1559         typedef typename OriginalFunctor::Parm9 Parm8;
1560         typedef typename OriginalFunctor::Parm10 Parm9;
1561         typedef typename OriginalFunctor::Parm11 Parm10;
1562         typedef typename OriginalFunctor::Parm12 Parm11;
1563         typedef typename OriginalFunctor::Parm13 Parm12;
1564         typedef typename OriginalFunctor::Parm14 Parm13;
1565         typedef typename OriginalFunctor::Parm15 Parm14;
1566         typedef EmptyType Parm15;
1567
1568 public:
1569
1570         BinderFirst(const OriginalFunctor &fun, BoundType bound)
1571                 : f_(fun), b_(bound)
1572         {}
1573
1574         LOKI_DEFINE_CLONE_FUNCTORIMPL(BinderFirst)
1575
1576 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
1577
1578         bool operator==(const typename Base::FunctorImplBaseType &rhs) const
1579         {
1580                 if(typeid(*this) != typeid(rhs))
1581                         return false; // cannot be equal
1582                 // if this line gives a compiler error, you are using a function object.
1583                 // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
1584                 return    f_ == ((static_cast<const BinderFirst &> (rhs)).f_) &&
1585                           b_ == ((static_cast<const BinderFirst &> (rhs)).b_);
1586         }
1587 #endif
1588
1589         // operator() implementations for up to 15 arguments
1590
1591         ResultType operator()()
1592         {
1593                 return f_(b_);
1594         }
1595
1596         ResultType operator()(Parm1 p1)
1597         {
1598                 return f_(b_, p1);
1599         }
1600
1601         ResultType operator()(Parm1 p1, Parm2 p2)
1602         {
1603                 return f_(b_, p1, p2);
1604         }
1605
1606         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
1607         {
1608                 return f_(b_, p1, p2, p3);
1609         }
1610
1611         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
1612         {
1613                 return f_(b_, p1, p2, p3, p4);
1614         }
1615
1616         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
1617         {
1618                 return f_(b_, p1, p2, p3, p4, p5);
1619         }
1620
1621         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1622                               Parm6 p6)
1623         {
1624                 return f_(b_, p1, p2, p3, p4, p5, p6);
1625         }
1626
1627         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1628                               Parm6 p6, Parm7 p7)
1629         {
1630                 return f_(b_, p1, p2, p3, p4, p5, p6, p7);
1631         }
1632
1633         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1634                               Parm6 p6, Parm7 p7, Parm8 p8)
1635         {
1636                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8);
1637         }
1638
1639         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1640                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
1641         {
1642                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9);
1643         }
1644
1645         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1646                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
1647         {
1648                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
1649         }
1650
1651         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1652                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
1653         {
1654                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
1655         }
1656
1657         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1658                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1659                               Parm12 p12)
1660         {
1661                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
1662         }
1663
1664         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1665                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1666                               Parm12 p12, Parm13 p13)
1667         {
1668                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
1669         }
1670
1671         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1672                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1673                               Parm12 p12, Parm13 p13, Parm14 p14)
1674         {
1675                 return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1676                           p14);
1677         }
1678
1679 private:
1680         OriginalFunctor f_;
1681         BoundTypeStorage b_;
1682 };
1683
1684 ////////////////////////////////////////////////////////////////////////////////
1685 ///  Binds the first parameter of a Functor object to a specific value
1686 ///  \ingroup FunctorGroup
1687 ////////////////////////////////////////////////////////////////////////////////
1688
1689 template <class Fctor>
1690 typename Private::BinderFirstTraits<Fctor>::BoundFunctorType
1691 BindFirst(
1692     const Fctor &fun,
1693     typename Fctor::Parm1 bound)
1694 {
1695         typedef typename Private::BinderFirstTraits<Fctor>::BoundFunctorType
1696         Outgoing;
1697
1698         return Outgoing(std::auto_ptr<typename Outgoing::Impl>(
1699                             new BinderFirst<Fctor>(fun, bound)));
1700 }
1701
1702 ////////////////////////////////////////////////////////////////////////////////
1703 ///  \class Chainer
1704 ///
1705 ///  \ingroup FunctorGroup
1706 ///   Chains two functor calls one after another
1707 ////////////////////////////////////////////////////////////////////////////////
1708
1709 template <typename Fun1, typename Fun2>
1710 class Chainer : public Fun2::Impl
1711 {
1712         typedef Fun2 Base;
1713
1714 public:
1715         typedef typename Base::ResultType ResultType;
1716         typedef typename Base::Parm1 Parm1;
1717         typedef typename Base::Parm2 Parm2;
1718         typedef typename Base::Parm3 Parm3;
1719         typedef typename Base::Parm4 Parm4;
1720         typedef typename Base::Parm5 Parm5;
1721         typedef typename Base::Parm6 Parm6;
1722         typedef typename Base::Parm7 Parm7;
1723         typedef typename Base::Parm8 Parm8;
1724         typedef typename Base::Parm9 Parm9;
1725         typedef typename Base::Parm10 Parm10;
1726         typedef typename Base::Parm11 Parm11;
1727         typedef typename Base::Parm12 Parm12;
1728         typedef typename Base::Parm13 Parm13;
1729         typedef typename Base::Parm14 Parm14;
1730         typedef typename Base::Parm15 Parm15;
1731
1732         Chainer(const Fun1 &fun1, const Fun2 &fun2) : f1_(fun1), f2_(fun2) {}
1733
1734         LOKI_DEFINE_CLONE_FUNCTORIMPL(Chainer)
1735
1736 #ifdef LOKI_FUNCTORS_ARE_COMPARABLE
1737
1738         bool operator==(const typename Base::Impl::FunctorImplBaseType &rhs) const
1739         {
1740                 if(typeid(*this) != typeid(rhs))
1741                         return false; // cannot be equal
1742                 // if this line gives a compiler error, you are using a function object.
1743                 // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
1744                 return    f1_ == ((static_cast<const Chainer &> (rhs)).f2_) &&
1745                           f2_ == ((static_cast<const Chainer &> (rhs)).f1_);
1746         }
1747 #endif
1748
1749         // operator() implementations for up to 15 arguments
1750
1751         ResultType operator()()
1752         {
1753                 return f1_(), f2_();
1754         }
1755
1756         ResultType operator()(Parm1 p1)
1757         {
1758                 return f1_(p1), f2_(p1);
1759         }
1760
1761         ResultType operator()(Parm1 p1, Parm2 p2)
1762         {
1763                 return f1_(p1, p2), f2_(p1, p2);
1764         }
1765
1766         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
1767         {
1768                 return f1_(p1, p2, p3), f2_(p1, p2, p3);
1769         }
1770
1771         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
1772         {
1773                 return f1_(p1, p2, p3, p4), f2_(p1, p2, p3, p4);
1774         }
1775
1776         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
1777         {
1778                 return f1_(p1, p2, p3, p4, p5), f2_(p1, p2, p3, p4, p5);
1779         }
1780
1781         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1782                               Parm6 p6)
1783         {
1784                 return f1_(p1, p2, p3, p4, p5, p6), f2_(p1, p2, p3, p4, p5, p6);
1785         }
1786
1787         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1788                               Parm6 p6, Parm7 p7)
1789         {
1790                 return f1_(p1, p2, p3, p4, p5, p6, p7),
1791                        f2_(p1, p2, p3, p4, p5, p6, p7);
1792         }
1793
1794         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1795                               Parm6 p6, Parm7 p7, Parm8 p8)
1796         {
1797                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8),
1798                        f2_(p1, p2, p3, p4, p5, p6, p7, p8);
1799         }
1800
1801         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1802                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
1803         {
1804                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9),
1805                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9);
1806         }
1807
1808         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1809                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
1810         {
1811                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10),
1812                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
1813         }
1814
1815         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1816                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
1817         {
1818                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11),
1819                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
1820         }
1821
1822         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1823                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1824                               Parm12 p12)
1825         {
1826                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12),
1827                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
1828         }
1829
1830         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1831                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1832                               Parm12 p12, Parm13 p13)
1833         {
1834                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13),
1835                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
1836         }
1837
1838         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1839                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1840                               Parm12 p12, Parm13 p13, Parm14 p14)
1841         {
1842                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1843                            p14),
1844                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1845                            p14);
1846         }
1847
1848         ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1849                               Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
1850                               Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
1851         {
1852                 return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1853                            p14, p15),
1854                        f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
1855                            p14, p15);
1856         }
1857
1858 private:
1859         Fun1 f1_;
1860         Fun2 f2_;
1861 };
1862
1863 ////////////////////////////////////////////////////////////////////////////////
1864 ///  Chains two functor calls one after another
1865 ///  \ingroup FunctorGroup
1866 ////////////////////////////////////////////////////////////////////////////////
1867
1868
1869 template <class Fun1, class Fun2>
1870 Fun2 Chain(
1871     const Fun1 &fun1,
1872     const Fun2 &fun2)
1873 {
1874         return Fun2(std::auto_ptr<typename Fun2::Impl>(
1875                         new Chainer<Fun1, Fun2>(fun1, fun2)));
1876 }
1877
1878 } // namespace Loki
1879
1880
1881 #endif // end file guardian
1882