vigra - vigra/metaprogramming.hxx Source File

[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

metaprogramming.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36 #ifndef VIGRA_METAPROGRAMMING_HXX
37 #define VIGRA_METAPROGRAMMING_HXX
38
39 #include "config.hxx"
40 #include <climits>
41 #include <limits>
42 #include <algorithm>
43
44 namespace vigra {
45
46 // mask cl.exe shortcomings [begin]
47 #if defined(_MSC_VER)
48 #pragma warning( push )
49 #pragma warning( disable : 4503 )
50 #endif
51
52 template <int N>
53 class MetaInt
54 {
55 public:
56 static const int value = N;
57 };
58
59 template <int N1, int N2>
60 class MetaMax
61 {
62 public:
63 static const int value = N1 < N2 ? N2 : N1;
64 };
65
66 template <int N1, int N2>
67 class MetaMin
68 {
69 public:
70 static const int value = N1 < N2 ? N1 : N2;
71 };
72
73 struct VigraTrueType
74 {
75 static const bool asBool = true, value = true;
76 };
77
78 struct VigraFalseType
79 {
80 static const bool asBool = false, value = false;
81 };
82
83 /** \addtogroup MultiArrayTags Multi-dimensional Array Tags
84 Meta-programming tags to mark array's as strided or unstrided.
85 */
86
87 //@{
88
89 /********************************************************/
90 /* */
91 /* tags for MultiArray memory layout */
92 /* */
93 /********************************************************/
94
95 /** tag for marking a MultiArray strided.
96
97 <b>\#include</b> <vigra/metaprogramming.hxx> <br/>
98 Namespace: vigra
99 */
100 struct StridedArrayTag {};
101
102 /** tag for marking a MultiArray unstrided.
103
104 <b>\#include</b> <vigra/metaprogramming.hxx> <br/>
105 Namespace: vigra
106 */
107 struct UnstridedArrayTag {};
108
109 /** tag for marking a MultiArray chunked.
110
111 <b>\#include</b> <vigra/metaprogramming.hxx> <br/>
112 Namespace: vigra
113 */
114 struct ChunkedArrayTag {};
115
116 /********************************************************/
117 /* */
118 /* TypeTraits */
119 /* */
120 /********************************************************/
121
122 template<class T>
123 class TypeTraits
124 {
125 public:
126 typedef VigraFalseType isConst;
127 typedef VigraFalseType isPOD;
128 typedef VigraFalseType isBuiltinType;
129 };
130
131 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
132
133 template<class T>
134 class TypeTraits<T const>
135 : public TypeTraits<T>
136 {
137 public:
138 typedef VigraTrueType isConst;
139 };
140
141 template<class T>
142 class TypeTraits<T *>
143 {
144 public:
145 typedef VigraFalseType isConst;
146 typedef VigraTrueType isPOD;
147 typedef VigraTrueType isBuiltinType;
148 };
149
150 template<class T>
151 class TypeTraits<T const *>
152 {
153 public:
154 typedef VigraFalseType isConst;
155 typedef VigraTrueType isPOD;
156 typedef VigraTrueType isBuiltinType;
157 };
158
159 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
160
161 namespace detail {
162
163 template <int size>
164 struct SizeToType;
165
166 } // namespace detail
167
168 #define VIGRA_TYPE_TRAITS(type, size) \
169 template<> \
170 class TypeTraits<type> \
171 { \
172 public: \
173 typedef VigraFalseType isConst; \
174 typedef VigraTrueType isPOD; \
175 typedef VigraTrueType isBuiltinType; \
176 typedef char TypeToSize[size]; \
177 }; \
178 \
179 namespace detail { \
180 TypeTraits<type>::TypeToSize * typeToSize(type); \
181 \
182 template <> \
183 struct SizeToType<size> \
184 { \
185 typedef type result; \
186 }; \
187 }
188
189 VIGRA_TYPE_TRAITS(char, 1)
190 VIGRA_TYPE_TRAITS(signed char, 2)
191 VIGRA_TYPE_TRAITS(unsigned char, 3)
192 VIGRA_TYPE_TRAITS(short, 4)
193 VIGRA_TYPE_TRAITS(unsigned short, 5)
194 VIGRA_TYPE_TRAITS(int, 6)
195 VIGRA_TYPE_TRAITS(unsigned int, 7)
196 VIGRA_TYPE_TRAITS(long, 8)
197 VIGRA_TYPE_TRAITS(unsigned long, 9)
198 VIGRA_TYPE_TRAITS(float, 10)
199 VIGRA_TYPE_TRAITS(double, 11)
200 VIGRA_TYPE_TRAITS(long double, 12)
201 #ifdef LLONG_MAX
202 VIGRA_TYPE_TRAITS(long long, 13)
203 VIGRA_TYPE_TRAITS(unsigned long long, 14)
204 #endif
205
206 #undef VIGRA_TYPE_TRAITS
207
208 //@}
209
210 template <class A>
211 struct Not;
212
213 template <>
214 struct Not<VigraTrueType>
215 {
216 typedef VigraFalseType result; // deprecated
217 static const bool boolResult = false; // deprecated
218 typedef VigraFalseType type;
219 static const bool value = false;
220 };
221
222 template <>
223 struct Not<VigraFalseType>
224 {
225 typedef VigraTrueType result; // deprecated
226 static const bool boolResult = true; // deprecated
227 typedef VigraTrueType type;
228 static const bool value = true;
229 };
230
231 template <class L, class R>
232 struct And;
233
234 template <>
235 struct And<VigraFalseType, VigraFalseType>
236 {
237 typedef VigraFalseType result; // deprecated
238 static const bool boolResult = false; // deprecated
239 typedef VigraFalseType type;
240 static const bool value = false;
241 };
242
243 template <>
244 struct And<VigraFalseType, VigraTrueType>
245 {
246 typedef VigraFalseType result; // deprecated
247 static const bool boolResult = false; // deprecated
248 typedef VigraFalseType type;
249 static const bool value = false;
250 };
251
252 template <>
253 struct And<VigraTrueType, VigraFalseType>
254 {
255 typedef VigraFalseType result; // deprecated
256 static const bool boolResult = false; // deprecated
257 typedef VigraFalseType type;
258 static const bool value = false;
259 };
260
261 template <>
262 struct And<VigraTrueType, VigraTrueType>
263 {
264 typedef VigraTrueType result; // deprecated
265 static const bool boolResult = true; // deprecated
266 typedef VigraTrueType type;
267 static const bool value = true;
268 };
269
270 template <class L, class R>
271 struct Or;
272
273 template <>
274 struct Or<VigraFalseType, VigraFalseType>
275 {
276 typedef VigraFalseType result; // deprecated
277 static const bool boolResult = false; // deprecated
278 typedef VigraFalseType type;
279 static const bool value = false;
280 };
281
282 template <>
283 struct Or<VigraTrueType, VigraFalseType>
284 {
285 typedef VigraTrueType result; // deprecated
286 static const bool boolResult = true; // deprecated
287 typedef VigraTrueType type;
288 static const bool value = true;
289 };
290
291 template <>
292 struct Or<VigraFalseType, VigraTrueType>
293 {
294 typedef VigraTrueType result; // deprecated
295 static const bool boolResult = true; // deprecated
296 typedef VigraTrueType type;
297 static const bool value = true;
298 };
299
300 template <>
301 struct Or<VigraTrueType, VigraTrueType>
302 {
303 typedef VigraTrueType result; // deprecated
304 static const bool boolResult = true; // deprecated
305 typedef VigraTrueType type;
306 static const bool value = true;
307 };
308
309 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
310
311 template <class PREDICATE, class TRUECASE, class FALSECASE>
312 struct If;
313
314 template <class TRUECASE, class FALSECASE>
315 struct If<VigraTrueType, TRUECASE, FALSECASE>
316 {
317 typedef TRUECASE type;
318 };
319
320 template <class TRUECASE, class FALSECASE>
321 struct If<VigraFalseType, TRUECASE, FALSECASE>
322 {
323 typedef FALSECASE type;
324 };
325
326 template <bool PREDICATE, class TRUECASE, class FALSECASE>
327 struct IfBool;
328
329 template <class TRUECASE, class FALSECASE>
330 struct IfBool<true, TRUECASE, FALSECASE>
331 {
332 typedef TRUECASE type;
333 };
334
335 template <class TRUECASE, class FALSECASE>
336 struct IfBool<false, TRUECASE, FALSECASE>
337 {
338 typedef FALSECASE type;
339 };
340
341 template <class L, class R>
342 struct IsSameType
343 {
344 typedef VigraFalseType result; // deprecated
345 static const bool boolResult = false; // deprecated
346 typedef VigraFalseType type;
347 static const bool value = false;
348 };
349
350 template <class T>
351 struct IsSameType<T, T>
352 {
353 typedef VigraTrueType result; // deprecated
354 static const bool boolResult = true; // deprecated
355 typedef VigraTrueType type;
356 static const bool value = true;
357 };
358
359 template <class L, class R>
360 struct IsDifferentType
361 {
362 typedef VigraTrueType type;
363 static const bool value = true;
364 };
365
366 template <class T>
367 struct IsDifferentType<T, T>
368 {
369 typedef VigraFalseType type;
370 static const bool value = false;
371 };
372
373 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
374
375 template <class From, class To>
376 struct IsConvertibleTo
377 {
378 typedef char falseResult[1];
379 typedef char trueResult[2];
380
381 static From const & check();
382
383 static falseResult * testIsConvertible(...);
384 static trueResult * testIsConvertible(To const &);
385
386 enum { resultSize = sizeof(*testIsConvertible(check())) };
387
388 static const bool value = (resultSize == 2);
389 typedef typename
390 IfBool<value, VigraTrueType, VigraFalseType>::type
391 type;
392 };
393
394 template <class DERIVED, class BASE>
395 struct IsDerivedFrom
396 {
397 typedef char falseResult[1];
398 typedef char trueResult[2];
399
400 static falseResult * testIsDerivedFrom(...);
401 static trueResult * testIsDerivedFrom(BASE const *);
402
403 enum { resultSize = sizeof(*testIsDerivedFrom(static_cast<DERIVED const *>(0))) };
404
405 static const bool value = (resultSize == 2);
406 typedef typename
407 IfBool<value, VigraTrueType, VigraFalseType>::type
408 type;
409
410 static const bool boolResult = value; // deprecated
411 typedef type result; // deprecated
412 };
413
414 template <class T>
415 struct UnqualifiedType
416 {
417 typedef T type;
418 static const bool isConst = false;
419 static const bool isReference = false;
420 static const bool isPointer = false;
421 };
422
423 template <class T>
424 struct UnqualifiedType<T const>
425 {
426 typedef T type;
427 static const bool isConst = true;
428 static const bool isReference = false;
429 static const bool isPointer = false;
430 };
431
432 template <class T>
433 struct UnqualifiedType<T &>
434 : public UnqualifiedType<T>
435 {
436 static const bool isReference = true;
437 };
438
439 template <class T>
440 struct UnqualifiedType<T const &>
441 : public UnqualifiedType<T const>
442 {
443 static const bool isReference = true;
444 };
445
446 template <class T>
447 struct UnqualifiedType<T *>
448 : public UnqualifiedType<T>
449 {
450 static const bool isPointer = true;
451 };
452
453 template <class T>
454 struct UnqualifiedType<T const *>
455 : public UnqualifiedType<T const>
456 {
457 static const bool isPointer = true;
458 };
459
460 template <bool, class T = void>
461 struct enable_if {};
462 template <class T>
463 struct enable_if<true, T> { typedef T type; };
464
465 struct sfinae_void;
466
467 template <class T, template<class> class USER>
468 struct sfinae_test
469 {
470 typedef char falseResult[1];
471 typedef char trueResult[2];
472
473 static falseResult * test(...);
474 static trueResult * test(USER<sfinae_void>);
475
476 enum { resultSize = sizeof(*test(static_cast<T*>(0))) };
477
478 static const bool value = (resultSize == 2);
479 typedef typename
480 IfBool<value, VigraTrueType, VigraFalseType>::type
481 type;
482 };
483
484 template <class T>
485 struct has_argument_type : public sfinae_test<T, has_argument_type>
486 {
487 template <class U> has_argument_type(U*, typename U::argument_type* = 0);
488 };
489
490 template <class T>
491 struct has_result_type : public sfinae_test<T, has_result_type>
492 {
493 template <class U> has_result_type(U*, typename U::result_type* = 0);
494 };
495
496 template <class T>
497 struct has_value_type : public sfinae_test<T, has_value_type>
498 {
499 template <class U> has_value_type(U*, typename U::value_type* = 0);
500 };
501
502 template <class T>
503 struct IsIterator : public sfinae_test<T, IsIterator>
504 {
505 template <class U> IsIterator(U*, typename U::iterator_category* = 0);
506 };
507
508 template <class T>
509 struct IsIterator<T*>
510 {
511 static const bool value = true;
512 typedef VigraTrueType type;
513 };
514
515 template <class T>
516 struct IsIterator<T const *>
517 {
518 static const bool value = true;
519 typedef VigraTrueType type;
520 };
521
522 template <class T>
523 struct has_real_promote_type : public sfinae_test<T, has_real_promote_type>
524 {
525 template <class U>
526 has_real_promote_type(U*, typename U::real_promote_type* = 0);
527 };
528
529 template <class T, bool P = has_real_promote_type<T>::value>
530 struct get_optional_real_promote
531 {
532 typedef T type;
533 };
534 template <class T>
535 struct get_optional_real_promote<T, true>
536 {
537 typedef typename T::real_promote_type type;
538 };
539
540 template <class T>
541 struct IsArray
542 {
543 typedef char falseResult[1];
544 typedef char trueResult[2];
545
546 static falseResult * test(...);
547 template <class U, unsigned n>
548 static trueResult * test(U (*)[n]);
549
550 enum { resultSize = sizeof(*test(static_cast<T*>(0))) };
551
552 static const bool value = (resultSize == 2);
553 typedef typename
554 IfBool<value, VigraTrueType, VigraFalseType>::type
555 type;
556 };
557
558
559 template <class D, class B, class Z> inline
560 D & static_cast_2(Z & z)
561 {
562 return static_cast<D &>(static_cast<B &>(z));
563 }
564
565 template <class A>
566 class copy_if_same_as
567 {
568 const bool copied;
569 const A *const data;
570 copy_if_same_as(const copy_if_same_as &);
571 void operator=(const copy_if_same_as &);
572 public:
573 copy_if_same_as(const A & x, const A & y)
574 : copied(&x == &y), data(copied ? new A(y) : &x) {}
575 ~copy_if_same_as()
576 {
577 if (copied)
578 delete data;
579 }
580 const A & operator()() const { return *data; }
581 };
582
583
584 template <class>
585 struct true_test : public VigraTrueType {};
586
587 template <class>
588 struct false_test : VigraFalseType {};
589
590 template <class PC, class T, class F>
591 struct ChooseBool
592 {
593 static const bool value = IfBool<PC::value, T, F>::type::value;
594 };
595
596 template <bool>
597 struct choose_type
598 {
599 template <class A, class B>
600 static const A & at(const A & a, const B &) { return a; }
601 template <class A, class B>
602 static A & at( A & a, B &) { return a; }
603 };
604 template <>
605 struct choose_type<false>
606 {
607 template <class A, class B>
608 static const B & at(const A &, const B & b) { return b; }
609 template <class A, class B>
610 static B & at( A &, B & b) { return b; }
611 };
612
613 template <class X>
614 struct HasMetaLog2
615 {
616 static const bool value = !std::numeric_limits<X>::is_signed
617 && std::numeric_limits<X>::is_integer;
618 };
619 template <class X>
620 struct EnableMetaLog2
621 : public enable_if<HasMetaLog2<X>::value> {};
622 template <class>
623 class vigra_error_MetaLog2_accepts_only_unsigned_types_and_no_;
624
625 // use a conforming template depth here (below 15 for up to 128 bits)
626 template <class X = unsigned long,
627 X n = ~(X(0)), unsigned s = 1, unsigned t = 0, bool q = 1,
628 X m = 0, X z = 0, X u = 1, class = void>
629 class MetaLog2
630 : public vigra_error_MetaLog2_accepts_only_unsigned_types_and_no_<X>
631 {};
632 template <class X, X n, unsigned s, unsigned t, bool q, X m, X z, X u>
633 struct MetaLog2 <X, n, s, t, q, m, z, u, typename EnableMetaLog2<X>::type>
634 {
635 static const unsigned value
636 = t + MetaLog2<X, (n >> s), s * (1 + q), s, !q, n / 2, z, u>::value;
637 };
638 template <class X, unsigned s, unsigned t, bool q, X m, X z, X u>
639 struct MetaLog2<X, z, s, t, q, m, z, u, typename EnableMetaLog2<X>::type>
640 {
641 static const unsigned value
642 = 1 + MetaLog2<X, m / 2, 2, 1, 1, 0, z, u>::value;
643 };
644 template <class X, unsigned s, unsigned t, bool q, X z, X u>
645 struct MetaLog2<X, z, s, t, q, u, z, u, typename EnableMetaLog2<X>::type>
646 {
647 static const unsigned value = 2;
648 };
649 template <class X, unsigned s, unsigned t, bool q, X z, X u>
650 struct MetaLog2<X, z, s, t, q, z, z, u, typename EnableMetaLog2<X>::type>
651 {
652 static const unsigned value = 1;
653 };
654 template <class X, X z, X u>
655 struct MetaLog2<X, z, 1, 0, 1, z, z, u, typename EnableMetaLog2<X>::type>
656 {
657 // A value of zero for MetaLog2<X, 0> is likely to cause most harm,
658 // such as division by zero or zero array sizes, this is actually indended.
659 static const unsigned value = 0;
660 };
661
662 template <int X, unsigned int N>
663 struct MetaPow
664 {
665 static const long long value = MetaPow<X, N-1>::value * X;
666 };
667
668 template <int X>
669 struct MetaPow<X, 0>
670 {
671 static const long long value = 1;
672 };
673
674 /****************************************************************************/
675 /* */
676 /* TypeList and its functions */
677 /* */
678 /****************************************************************************/
679
680 template<class HEAD, class TAIL=void>
681 struct TypeList
682 {
683 typedef TypeList<HEAD, TAIL> type;
684 typedef HEAD Head;
685 typedef TAIL Tail;
686 };
687
688 template <class List, class T>
689 struct Contains;
690
691 template <class Head, class Tail, class T>
692 struct Contains<TypeList<Head, Tail>, T>
693 {
694 typedef typename Contains<Tail, T>::type type;
695 };
696
697 template <class Head, class Tail>
698 struct Contains<TypeList<Head, Tail>, Head>
699 {
700 typedef VigraTrueType type;
701 };
702
703 template <class T>
704 struct Contains<void, T>
705 {
706 typedef VigraFalseType type;
707 };
708
709 template <class List, class T>
710 struct Remove;
711
712 template <class Head, class Tail, class T>
713 struct Remove<TypeList<Head, Tail>, T>
714 {
715 typedef TypeList<Head, typename Remove<Tail, T>::type> type;
716 };
717
718 template <class Head, class Tail>
719 struct Remove<TypeList<Head, Tail>, Head>
720 {
721 typedef Tail type;
722 };
723
724 template <class T>
725 struct Remove<void, T>
726 {
727 typedef void type;
728 };
729
730 template <class A, class Tail=void>
731 struct Push
732 {
733 typedef TypeList<A, typename Tail::type> type;
734 };
735
736 template <class Head, class Tail, class List>
737 struct Push<TypeList<Head, Tail>, List>
738 {
739 typedef typename Push<Tail, List>::type Rest;
740 typedef TypeList<Head, Rest> type;
741 };
742
743 template <class Head, class Tail>
744 struct Push<TypeList<Head, Tail>, void>
745 {
746 typedef TypeList<Head, Tail> type;
747 };
748
749 template <class A>
750 struct Push<A, void>
751 {
752 typedef TypeList<A> type;
753 };
754
755 template <class A>
756 struct Push<void, A>
757 {
758 typedef A type;
759 };
760
761 template <>
762 struct Push<void, void>
763 {
764 typedef void type;
765 };
766
767 template <class A, class Tail=void>
768 struct PushUnique
769 {
770 typedef typename Contains<Tail, A>::type AlreadyInList;
771 typedef typename If<AlreadyInList, typename Tail::type, TypeList<A, typename Tail::type> >::type type;
772 };
773
774 template <class Head, class Tail, class List>
775 struct PushUnique<TypeList<Head, Tail>, List>
776 {
777 typedef typename PushUnique<Tail, List>::type Rest;
778 typedef typename Contains<Rest, Head>::type HeadAlreadyInList;
779 typedef typename If<HeadAlreadyInList, Rest, TypeList<Head, Rest> >::type type;
780 };
781
782 template <class Head, class Tail>
783 struct PushUnique<TypeList<Head, Tail>, void>
784 {
785 typedef TypeList<Head, Tail> type;
786 };
787
788 template <class A>
789 struct PushUnique<A, void>
790 {
791 typedef TypeList<A> type;
792 };
793
794 template <class A>
795 struct PushUnique<void, A>
796 {
797 typedef A type;
798 };
799
800 template <>
801 struct PushUnique<void, void>
802 {
803 typedef void type;
804 };
805
806 template <class T01=void, class T02=void, class T03=void, class T04=void, class T05=void,
807 class T06=void, class T07=void, class T08=void, class T09=void, class T10=void,
808 class T11=void, class T12=void, class T13=void, class T14=void, class T15=void,
809 class T16=void, class T17=void, class T18=void, class T19=void, class T20=void>
810 struct MakeTypeList
811 {
812 typedef typename Push<T19, T20>::type L19;
813 typedef typename Push<T18, L19>::type L18;
814 typedef typename Push<T17, L18>::type L17;
815 typedef typename Push<T16, L17>::type L16;
816 typedef typename Push<T15, L16>::type L15;
817 typedef typename Push<T14, L15>::type L14;
818 typedef typename Push<T13, L14>::type L13;
819 typedef typename Push<T12, L13>::type L12;
820 typedef typename Push<T11, L12>::type L11;
821 typedef typename Push<T10, L11>::type L10;
822 typedef typename Push<T09, L10>::type L09;
823 typedef typename Push<T08, L09>::type L08;
824 typedef typename Push<T07, L08>::type L07;
825 typedef typename Push<T06, L07>::type L06;
826 typedef typename Push<T05, L06>::type L05;
827 typedef typename Push<T04, L05>::type L04;
828 typedef typename Push<T03, L04>::type L03;
829 typedef typename Push<T02, L03>::type L02;
830 typedef typename Push<T01, L02>::type L01;
831 typedef L01 type;
832 };
833
834 template <class T01=void, class T02=void, class T03=void, class T04=void, class T05=void,
835 class T06=void, class T07=void, class T08=void, class T09=void, class T10=void,
836 class T11=void, class T12=void, class T13=void, class T14=void, class T15=void,
837 class T16=void, class T17=void, class T18=void, class T19=void, class T20=void>
838 struct MakeTypeListUnique
839 {
840 typedef typename PushUnique<T19, T20>::type L19;
841 typedef typename PushUnique<T18, L19>::type L18;
842 typedef typename PushUnique<T17, L18>::type L17;
843 typedef typename PushUnique<T16, L17>::type L16;
844 typedef typename PushUnique<T15, L16>::type L15;
845 typedef typename PushUnique<T14, L15>::type L14;
846 typedef typename PushUnique<T13, L14>::type L13;
847 typedef typename PushUnique<T12, L13>::type L12;
848 typedef typename PushUnique<T11, L12>::type L11;
849 typedef typename PushUnique<T10, L11>::type L10;
850 typedef typename PushUnique<T09, L10>::type L09;
851 typedef typename PushUnique<T08, L09>::type L08;
852 typedef typename PushUnique<T07, L08>::type L07;
853 typedef typename PushUnique<T06, L07>::type L06;
854 typedef typename PushUnique<T05, L06>::type L05;
855 typedef typename PushUnique<T04, L05>::type L04;
856 typedef typename PushUnique<T03, L04>::type L03;
857 typedef typename PushUnique<T02, L03>::type L02;
858 typedef typename PushUnique<T01, L02>::type L01;
859 typedef L01 type;
860 };
861
862 // mask cl.exe shortcomings [end]
863 #if defined(_MSC_VER)
864 #pragma warning( pop )
865 #endif
866
867 } // namespace vigra
868
869 #endif /* VIGRA_METAPROGRAMMING_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.10.0 (Thu Jan 8 2015)