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

type_lists.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2011-2012 by Markus Nullmeier and 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_TYPE_LISTS_HXX
37 #define VIGRA_TYPE_LISTS_HXX
38
39 #include <iostream>
40 #include <typeinfo>
41 #include <utility>
42 #include <algorithm>
43 #include "metaprogramming.hxx"
44 #include "bit_array.hxx"
45 #include "error.hxx"
46
47 namespace vigra {
48
49 // mask cl.exe shortcomings [begin]
50 #if defined(_MSC_VER)
51 #pragma warning( push )
52 #pragma warning( disable : 4503 )
53 #endif
54
55 namespace type_lists {
56
57 struct nil; // end-of-list marker.
58 template <class T>
59 struct nil_t;
60
61 // type lists of size >= 1.
62
63 template <class A, class B = nil> struct cons
64 {
65 typedef A first;
66 typedef B rest;
67 };
68
69 template <class X, class A, class B> struct if_nil
70 {
71 typedef B type;
72 };
73 template <class A, class B> struct if_nil <nil, A, B>
74 {
75 typedef A type;
76 };
77
78 // truncate type list L (using class NIL as ending marker)
79 // at the first occurence of type X
80 template <class X, class L, class NIL = nil> struct truncate
81 {
82 typedef cons<typename L::first,
83 typename truncate<X, typename L::rest, NIL>::type> type;
84 };
85 template <class L, class NIL> struct truncate<typename L::first, L, NIL>
86 {
87 typedef nil type; // do the actual truncation
88 };
89 template <class X, class NIL> struct truncate<X, NIL, NIL>
90 {
91 typedef nil type;
92 };
93
94 template <class NIL, class A = NIL, class B = NIL, class C = NIL,
95 class D = NIL, class E = NIL, class F = NIL,
96 class G = NIL, class H = NIL, class I = NIL,
97 class J = NIL, class K = NIL, class L = NIL,
98 class M = NIL, class N = NIL, class O = NIL,
99 class P = NIL, class Q = NIL, class R = NIL,
100 class S = NIL, class T = NIL, class U = NIL,
101 class V = NIL, class W = NIL, class X = NIL,
102 class Y = NIL, class Z = NIL>
103 struct make_list_nil {
104 typedef typename truncate<NIL, cons<A, cons<B, cons<C, cons<D, cons<E,
105 cons<F, cons<G, cons<H, cons<I, cons<J,
106 cons<K, cons<L, cons<M, cons<N, cons<O,
107 cons<P, cons<Q, cons<R, cons<S, cons<T,
108 cons<U, cons<V, cons<W, cons<X, cons<Y,
109 cons<Z, NIL> > > > > > > > > > > > > > >
110 > > > > > > > > > > >, NIL>::type type;
111 };
112
113 template <class A = nil, class B = nil, class C = nil, class D = nil,
114 class E = nil, class F = nil, class G = nil, class H = nil,
115 class I = nil, class J = nil, class K = nil, class L = nil,
116 class M = nil, class N = nil, class O = nil, class P = nil,
117 class Q = nil, class R = nil, class S = nil, class T = nil,
118 class U = nil, class V = nil, class W = nil, class X = nil,
119 class Y = nil, class Z = nil>
120
121 struct make_list {
122 typedef typename make_list_nil<nil, A, B, C, D, E, F, G, H, I,
123 J, K, L, M, N, O, P, Q, R,
124 S, T, U, V, W, X, Y, Z
125 >::type type;
126 };
127
128 template <class T_, template<class> class A = nil_t,
129 template<class> class B = nil_t,
130 template<class> class C = nil_t,
131 template<class> class D = nil_t,
132 template<class> class E = nil_t,
133 template<class> class F = nil_t,
134 template<class> class G = nil_t,
135 template<class> class H = nil_t,
136 template<class> class I = nil_t,
137 template<class> class J = nil_t,
138 template<class> class K = nil_t,
139 template<class> class L = nil_t,
140 template<class> class M = nil_t,
141 template<class> class N = nil_t,
142 template<class> class O = nil_t,
143 template<class> class P = nil_t,
144 template<class> class Q = nil_t,
145 template<class> class R = nil_t,
146 template<class> class S = nil_t,
147 template<class> class T = nil_t,
148 template<class> class U = nil_t,
149 template<class> class V = nil_t,
150 template<class> class W = nil_t,
151 template<class> class X = nil_t,
152 template<class> class Y = nil_t,
153 template<class> class Z = nil_t>
154 struct make_list_template {
155 typedef typename make_list_nil<nil_t<T_>,
156 A<T_>, B<T_>, C<T_>, D<T_>, E<T_>,
157 F<T_>, G<T_>, H<T_>, I<T_>, J<T_>,
158 K<T_>, L<T_>, M<T_>, N<T_>, O<T_>,
159 P<T_>, Q<T_>, R<T_>, S<T_>, T<T_>,
160 U<T_>, V<T_>, W<T_>, X<T_>, Y<T_>,
161 Z<T_> >::type type;
162 };
163
164 // a means to partially compensate for the lack of templated typedefs.
165 template <template<class, class> class BASE, class T_,
166 template<class> class A = nil_t,
167 template<class> class B = nil_t,
168 template<class> class C = nil_t,
169 template<class> class D = nil_t,
170 template<class> class E = nil_t,
171 template<class> class F = nil_t,
172 template<class> class G = nil_t,
173 template<class> class H = nil_t,
174 template<class> class I = nil_t,
175 template<class> class J = nil_t,
176 template<class> class K = nil_t,
177 template<class> class L = nil_t,
178 template<class> class M = nil_t,
179 template<class> class N = nil_t,
180 template<class> class O = nil_t,
181 template<class> class P = nil_t,
182 template<class> class Q = nil_t,
183 template<class> class R = nil_t,
184 template<class> class S = nil_t,
185 template<class> class T = nil_t,
186 template<class> class U = nil_t,
187 template<class> class V = nil_t,
188 template<class> class W = nil_t,
189 template<class> class X = nil_t,
190 template<class> class Y = nil_t,
191 template<class> class Z = nil_t>
192 struct use_template_list
193 : public BASE<T_, typename make_list_template<T_, A, B, C, D, E, F, G,
194 H, I, J, K, L, M, N,
195 O, P, Q, R, S, T, U,
196 V, W, X, Y, Z>::type>
197 {};
198
199 // use first and rest only when possible:
200 template <class T>
201 struct has_first_rest : public sfinae_test<T, has_first_rest>
202 {
203 template <class U>
204 has_first_rest(U*, typename U::first* = 0, typename U::rest* = 0);
205 };
206 template <bool P, class A>
207 struct cond_cons_rest;
208 template <class A>
209 struct cond_cons_rest<false, A>
210 {
211 typedef void* type;
212 };
213 template <class A>
214 struct cond_cons_rest<true, A>
215 {
216 typedef typename A::rest type;
217 };
218 // test if a type is a list in the above sense.
219 template <class A> struct is_list
220 {
221 static const bool value = is_list<typename
222 cond_cons_rest<has_first_rest<A>::value, A>::type>::value;
223 };
224 template <> struct is_list<nil>
225 {
226 static const bool value = true;
227 };
228 template <> struct is_list<void*>
229 {
230 static const bool value = false;
231 };
232
233 template <class A> struct list_guard
234 {
235 typedef typename IfBool<is_list<A>::value, A, nil>::type type;
236 };
237
238 template <class A> struct size
239 {
240 static const unsigned of = size<typename A::rest>::of + 1;
241 };
242 template <> struct size<nil>
243 {
244 static const unsigned of = 0;
245 };
246
247 template <class X, class L> struct append
248 {
249 typedef cons<typename L::first,
250 typename append<X, typename L::rest>::type> type;
251 };
252 template <class X> struct append<X, nil>
253 {
254 typedef cons<X, nil> type;
255 };
256 template <> struct append<nil, nil>
257 {
258 typedef nil type;
259 };
260
261 template <class L, class R = nil> struct reverse
262 {
263 typedef typename reverse<typename L::rest,
264 cons<typename L::first, R> >::type type;
265 };
266 template <class R> struct reverse<nil, R>
267 {
268 typedef R type;
269 };
270
271 template <template<class> class P, class Q, class L>
272 struct max_value
273 {
274 static const bool is_nil = false;
275 static const Q first_value = P<typename L::first>::value;
276 typedef max_value<P, Q, typename L::rest> rest_type;
277 static const Q rest_value = rest_type::value;
278 static const bool gt = first_value > rest_value || rest_type::is_nil;
279 static const Q value = gt * first_value + !gt * rest_value;
280 };
281 template <template<class> class P, class Q>
282 struct max_value<P, Q, nil>
283 {
284 static const Q value = 0;
285 static const bool is_nil = true;
286 };
287
288 // remove the all occurences of type X in type list L
289 template <class X, class L> struct remove // recursion
290 {
291 typedef cons<typename L::first,
292 typename remove<X, typename L::rest>::type> type;
293 };
294 template <class L> struct remove<typename L::first, L> // actual removal
295 {
296 typedef typename remove<typename L::first, typename L::rest>::type type;
297 };
298 template <class X> struct remove<X, nil> // list end
299 {
300 typedef nil type;
301 };
302
303 // remove the all occurences of type list L where predicate P equals value
304 template <template<class> class P, class L, bool value = true>
305 struct remove_if
306 {
307 typedef typename
308 IfBool<
309 value == P<typename L::first>::value, typename
310 remove_if<P, typename L::rest, value>::type,
311 cons<typename
312 L::first, typename
313 remove_if<P, typename L::rest, value>::type
314 >
315 >::type type;
316 };
317 template <template<class> class P, bool value>
318 struct remove_if<P, nil, value>
319 {
320 typedef nil type;
321 };
322
323 template <template<class> class P, class L>
324 struct remove_if_not
325 {
326 typedef typename remove_if<P, L, false>::type type;
327 };
328
329 template <class X, class L> struct contains
330 {
331 static const bool value = contains<X, typename L::rest>::value;
332 };
333 template <class L> struct contains<typename L::first, L>
334 {
335 static const bool value = true;
336 };
337 template <class X> struct contains<X, nil>
338 {
339 static const bool value = false;
340 };
341
342 // simple, unstable merge
343 template <class X, class L> struct merge
344 {
345 typedef typename L::first first;
346 typedef typename
347 merge<
348 typename IfBool<contains<first, X>::value,
349 X,
350 cons<first, X>
351 >::type,
352 typename L::rest
353 >::type type;
354 };
355 template <class X> struct merge<X, nil>
356 {
357 typedef X type;
358 };
359
360 // simple, unstable unique
361 template <class L> struct unique
362 {
363 typedef typename merge<nil, L>::type type;
364 };
365
366 template <class T_, template<class> class A = nil_t,
367 template<class> class B = nil_t,
368 template<class> class C = nil_t,
369 template<class> class D = nil_t,
370 template<class> class E = nil_t,
371 template<class> class F = nil_t,
372 template<class> class G = nil_t,
373 template<class> class H = nil_t,
374 template<class> class I = nil_t,
375 template<class> class J = nil_t,
376 template<class> class K = nil_t,
377 template<class> class L = nil_t,
378 template<class> class M = nil_t,
379 template<class> class N = nil_t,
380 template<class> class O = nil_t,
381 template<class> class P = nil_t,
382 template<class> class Q = nil_t,
383 template<class> class R = nil_t,
384 template<class> class S = nil_t,
385 template<class> class T = nil_t,
386 template<class> class U = nil_t,
387 template<class> class V = nil_t,
388 template<class> class W = nil_t,
389 template<class> class X = nil_t,
390 template<class> class Y = nil_t,
391 template<class> class Z = nil_t>
392 struct implies_template
393 {
394 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K,
395 L, M, N, O, P, Q, R, S, T, U, V,
396 W, X, Y, Z>::type implies_types;
397 };
398
399 template <class T_, template<class> class A = nil_t,
400 template<class> class B = nil_t,
401 template<class> class C = nil_t,
402 template<class> class D = nil_t,
403 template<class> class E = nil_t,
404 template<class> class F = nil_t,
405 template<class> class G = nil_t,
406 template<class> class H = nil_t,
407 template<class> class I = nil_t,
408 template<class> class J = nil_t,
409 template<class> class K = nil_t,
410 template<class> class L = nil_t,
411 template<class> class M = nil_t,
412 template<class> class N = nil_t,
413 template<class> class O = nil_t,
414 template<class> class P = nil_t,
415 template<class> class Q = nil_t,
416 template<class> class R = nil_t,
417 template<class> class S = nil_t,
418 template<class> class T = nil_t,
419 template<class> class U = nil_t,
420 template<class> class V = nil_t,
421 template<class> class W = nil_t,
422 template<class> class X = nil_t,
423 template<class> class Y = nil_t,
424 template<class> class Z = nil_t>
425 struct follows_template
426 {
427 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K,
428 L, M, N, O, P, Q, R, S, T, U, V,
429 W, X, Y, Z>::type follows_types;
430 };
431
432 template <class T_, template<class> class A = nil_t,
433 template<class> class B = nil_t,
434 template<class> class C = nil_t,
435 template<class> class D = nil_t,
436 template<class> class E = nil_t,
437 template<class> class F = nil_t,
438 template<class> class G = nil_t,
439 template<class> class H = nil_t,
440 template<class> class I = nil_t,
441 template<class> class J = nil_t,
442 template<class> class K = nil_t,
443 template<class> class L = nil_t,
444 template<class> class M = nil_t,
445 template<class> class N = nil_t,
446 template<class> class O = nil_t,
447 template<class> class P = nil_t,
448 template<class> class Q = nil_t,
449 template<class> class R = nil_t,
450 template<class> class S = nil_t,
451 template<class> class T = nil_t,
452 template<class> class U = nil_t,
453 template<class> class V = nil_t,
454 template<class> class W = nil_t,
455 template<class> class X = nil_t,
456 template<class> class Y = nil_t,
457 template<class> class Z = nil_t>
458 struct depends_on_template
459 {
460 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K,
461 L, M, N, O, P, Q, R, S, T, U, V,
462 W, X, Y, Z>::type depends_on;
463 };
464
465 template <class T_u, template<class> class A = nil_t,
466 template<class> class B = nil_t,
467 template<class> class C = nil_t,
468 template<class> class D = nil_t,
469 template<class> class E = nil_t,
470 template<class> class F = nil_t,
471 template<class> class G = nil_t,
472 template<class> class H = nil_t,
473 template<class> class I = nil_t,
474 template<class> class J = nil_t,
475 template<class> class K = nil_t,
476 template<class> class L = nil_t,
477 template<class> class M = nil_t,
478 template<class> class N = nil_t,
479 template<class> class O = nil_t,
480 template<class> class P = nil_t,
481 template<class> class Q = nil_t,
482 template<class> class R = nil_t,
483 template<class> class S = nil_t,
484 template<class> class T = nil_t,
485 template<class> class U = nil_t,
486 template<class> class V = nil_t,
487 template<class> class W = nil_t,
488 template<class> class X = nil_t,
489 template<class> class Y = nil_t,
490 template<class> class Z = nil_t>
491 struct uses_template
492 : public implies_template<T_u, A, B, C, D, E, F, G, H, I, J, K, L, M,
493 N, O, P, Q, R, S, T, U, V, W, X, Y, Z>,
494 public depends_on_template<T_u, A, B, C, D, E, F, G, H, I, J, K, L, M,
495 N, O, P, Q, R, S, T, U, V, W, X, Y, Z>
496 {
497 template <template<class> class A_ = nil_t,
498 template<class> class B_ = nil_t,
499 template<class> class C_ = nil_t,
500 template<class> class D_ = nil_t,
501 template<class> class E_ = nil_t,
502 template<class> class F_ = nil_t,
503 template<class> class G_ = nil_t,
504 template<class> class H_ = nil_t,
505 template<class> class I_ = nil_t,
506 template<class> class J_ = nil_t,
507 template<class> class K_ = nil_t,
508 template<class> class L_ = nil_t,
509 template<class> class M_ = nil_t,
510 template<class> class N_ = nil_t,
511 template<class> class O_ = nil_t,
512 template<class> class P_ = nil_t,
513 template<class> class Q_ = nil_t,
514 template<class> class R_ = nil_t,
515 template<class> class S_ = nil_t,
516 template<class> class T_ = nil_t,
517 template<class> class U_ = nil_t,
518 template<class> class V_ = nil_t,
519 template<class> class W_ = nil_t,
520 template<class> class X_ = nil_t,
521 template<class> class Y_ = nil_t,
522 template<class> class Z_ = nil_t>
523 struct follows
524 : public uses_template
525 , public follows_template<T_u, A_, B_, C_, D_, E_, F_, G_, H_, I_,
526 J_, K_, L_, M_, N_, O_, P_, Q_, R_,
527 S_, T_, U_, V_, W_, X_, Y_, Z_> {};
528
529 template <template<class> class A_ = nil_t,
530 template<class> class B_ = nil_t,
531 template<class> class C_ = nil_t,
532 template<class> class D_ = nil_t,
533 template<class> class E_ = nil_t,
534 template<class> class F_ = nil_t,
535 template<class> class G_ = nil_t,
536 template<class> class H_ = nil_t,
537 template<class> class I_ = nil_t,
538 template<class> class J_ = nil_t,
539 template<class> class K_ = nil_t,
540 template<class> class L_ = nil_t,
541 template<class> class M_ = nil_t,
542 template<class> class N_ = nil_t,
543 template<class> class O_ = nil_t,
544 template<class> class P_ = nil_t,
545 template<class> class Q_ = nil_t,
546 template<class> class R_ = nil_t,
547 template<class> class S_ = nil_t,
548 template<class> class T_ = nil_t,
549 template<class> class U_ = nil_t,
550 template<class> class V_ = nil_t,
551 template<class> class W_ = nil_t,
552 template<class> class X_ = nil_t,
553 template<class> class Y_ = nil_t,
554 template<class> class Z_ = nil_t>
555 struct implies
556 : public uses_template
557 {
558 typedef typename
559 merge<typename
560 uses_template::implies_types, typename
561 implies_template<T_u, A_, B_, C_, D_, E_, F_, G_, H_, I_,
562 J_, K_, L_, M_, N_, O_, P_, Q_, R_,
563 S_, T_, U_, V_, W_, X_, Y_, Z_>
564 ::implies_types
565 >::type
566 implies_types;
567 };
568 };
569
570 // for_all() helper class.
571 template <template<class> class EXEC, class L> struct for_exec
572 {
573 template <class TX>
574 static void all(TX & tx)
575 {
576 EXEC<typename L::first>::exec(tx);
577 for_exec<EXEC, typename L::rest>::all(tx);
578 }
579 };
580 template <template<class> class EXEC> struct for_exec<EXEC, nil>
581 {
582 template <class TX> static void all(TX &) {}
583 };
584 // for_all on type lists.
585 // for all types T in the list L,
586 // calls the static member function EXEC<T>::exec(TX & tx).
587 template <class L, template<class> class EXEC, class TX>
588 inline void for_all(TX & tx)
589 {
590 for_exec<EXEC, L>::all(tx);
591 }
592
593 template <class T>
594 struct has_depends_on : public sfinae_test<T, has_depends_on>
595 {
596 template <class U> has_depends_on(U*, typename U::depends_on* = 0);
597 };
598 template <class T>
599 struct has_implies : public sfinae_test<T, has_implies>
600 {
601 template <class U> has_implies(U*, typename U::implies_types* = 0);
602 };
603 template <class T>
604 struct has_follows : public sfinae_test<T, has_follows>
605 {
606 template <class U> has_follows(U*, typename U::follows_types* = 0);
607 };
608
609 // use empty list in case of lacking / faulty depends_on or implies_types:
610 template <bool P, class T>
611 struct depends_on_guard;
612 template <class T>
613 struct depends_on_guard<false, T>
614 {
615 typedef nil type;
616 };
617 template <class T>
618 struct depends_on_guard<true, T>
619 {
620 typedef typename list_guard<typename T::depends_on>::type type;
621 };
622 template <class T>
623 struct get_pure_depends_on
624 {
625 typedef typename depends_on_guard<has_depends_on<T>::value, T>::type
626 type;
627 };
628
629 template <bool P, class T>
630 struct follows_guard;
631 template <class T>
632 struct follows_guard<false, T>
633 {
634 typedef nil type;
635 };
636 template <class T>
637 struct follows_guard<true, T>
638 {
639 typedef typename list_guard<typename T::follows_types>::type type;
640 };
641 template <class T>
642 struct get_follows
643 {
644 typedef typename follows_guard<has_follows<T>::value, T>::type
645 type;
646 };
647
648 template <class T>
649 struct get_depends_on
650 {
651 typedef typename merge<typename get_pure_depends_on<T>::type,
652 typename get_follows<T>::type >::type type;
653 };
654
655 template <bool P, class T>
656 struct implies_guard;
657 template <class T>
658 struct implies_guard<false, T>
659 {
660 typedef nil type;
661 };
662 template <class T>
663 struct implies_guard<true, T>
664 {
665 typedef typename list_guard<typename T::implies_types>::type type;
666 };
667 template <class T>
668 struct get_implies
669 {
670 typedef typename implies_guard<has_implies<T>::value, T>::type
671 type;
672 };
673
674 template <class L> struct implies_expand
675 {
676 typedef typename L::first first;
677 typedef typename L::rest rest;
678 typedef
679 cons<first, typename
680 merge<typename
681 implies_expand<rest>::type, typename
682 implies_expand<typename
683 get_implies<first>
684 ::type>::type>::type> type;
685 };
686 template <> struct implies_expand<nil>
687 {
688 typedef nil type;
689 };
690
691 // for_all with type list == T::depends_on (if any.)
692 template <class T, template<class> class EXEC, class TX>
693 inline void for_all_used(TX & tx)
694 {
695 for_all<typename get_pure_depends_on<T>::type, EXEC>(tx);
696 }
697
698 template <class X, class T>
699 struct contains_dependent
700 {
701 static const bool value
702 = contains<X, typename get_depends_on<T>::type>::value;
703 };
704
705 template <class X, class XL> struct is_independent_on
706 {
707 static const bool value
708 = ChooseBool<contains_dependent<X, typename XL::first>,
709 VigraFalseType,
710 is_independent_on<X, typename XL::rest>
711 >::value;
712 };
713 template <class X> struct is_independent_on<X, nil>
714 {
715 static const bool value = true;
716 };
717
718 template <class XL, class YL = XL> struct get_independent
719 {
720 typedef typename YL::first YL_first;
721 typedef typename
722 IfBool<is_independent_on<YL_first, XL>::value,
723 YL_first,
724 typename get_independent<XL, typename YL::rest>::type
725 >::type type;
726 };
727 template <class XL> struct get_independent<XL, nil>
728 {
729 typedef nil type;
730 };
731
732 // the output is a list of types in reverse order, starting with the
733 // most depedent types.
734 template <class L> struct topo_sort
735 {
736 typedef typename get_independent<L>::type indep;
737 typedef typename
738 if_nil<indep,
739 nil,
740 cons<indep,
741 typename topo_sort<typename remove<indep, L>::type>::type
742 >
743 >::type type;
744 };
745 template <> struct topo_sort<nil>
746 {
747 typedef nil type;
748 };
749
750 // Topological sort -- the input is a list of types (see below),
751 // each of which may, optionally, have an embedded typedef 'depends_on'
752 // set to a singly-linked-list of types declared
753 // using vigra::type_lists::cons, such as
754 // cons<type_a, cons<type_b, cons<type_c> > >
755 // (a one-parameter cons will add the trailing nil automatically),
756 // -- the output is a list of types with increasing dependence,
757 // starting with the indepedent types.
758 // Types that should be said lists -- but are in fact not -- are silently
759 // replaced by empty lists.
760
761 template <class L> struct topological_sort
762 {
763 typedef typename
764 reverse<typename
765 topo_sort<typename
766 unique<typename
767 list_guard<L>
768 ::type>::type>::type>::type type;
769 };
770
771 template <class L> struct topological_sort_expanded
772 {
773 typedef typename
774 topological_sort<typename
775 implies_expand<L>
776 ::type>::type type;
777 };
778
779 template <class V, unsigned pos = 0>
780 class cond_val : public V
781 {
782 typedef V load_type;
783 protected:
784 bool is_set_;
785 public:
786 cond_val() : is_set_(false) {}
787 const V & val() const { return *this; }
788 V & val() { return *this; }
789
790 template <class TUPLE>
791 bool is_set(const TUPLE &) const
792 {
793 return is_set_;
794 }
795
796 template <class TUPLE>
797 void set(TUPLE &)
798 {
799 is_set_ = true;
800 }
801 template <class TUPLE>
802 void set(const V & v, TUPLE & tuple)
803 {
804 set(tuple);
805 val() = v;
806 }
807 friend std::ostream & operator<<(std::ostream & os, const cond_val & x)
808 {
809 if (x.is_set_)
810 os << x.val(x);
811 else
812 os << "<nil>";
813 return os;
814 }
815 };
816
817 template <class V, unsigned pos>
818 class bit_cond_val : public V
819 {
820 typedef V load_type;
821 public:
822 const V & val() const { return *this; }
823 V & val() { return *this; }
824
825 template <class TUPLE>
826 bool is_set(const TUPLE & tuple) const
827 {
828 return tuple.template is_bit_set<pos>();
829 }
830
831 template <class TUPLE>
832 void set(TUPLE & tuple)
833 {
834 tuple.template set_bit<pos>();
835 }
836 template <class TUPLE>
837 void set(const V & v, TUPLE & tuple)
838 {
839 set(tuple);
840 val() = v;
841 }
842 };
843
844 // no templated virtual functions in C++ ...
845 //
846 // simple_member_dispatch: sample base and polymorphic adapter classes
847 // for cond_virtual_tuple / etc.
848 // -- the names 'member_base_type' and 'load_type' of the templates,
849 // and also their parameter types, are fixed.
850 // -- note that the member_base_type template of any "member_dispatch"
851 // class can not directly serve as a base class for any member type that
852 // is used within the tuple, since the signatures of most of the
853 // virtual functions that are usually needed necessarily require the
854 // type of the tuple itself.
855 //
856 struct simple_member_dispatch
857 {
858 template <class ACX, class T>
859 struct member_base_type
860 {
861 virtual void operator()() {}
862 virtual void operator()(ACX &, const T &) {}
863 virtual void operator()(const ACX &, const ACX &, const ACX &) {}
864 virtual void call(ACX &, const T &, unsigned) {}
865 virtual ~member_base_type() {}
866 };
867 template <class ACX, class T, class V>
868 struct load_type : public member_base_type<ACX, T>, public V
869 {
870 load_type() {}
871 load_type(const V & v) : V(v) {}
872 void operator()()
873 {
874 V::operator()();
875 }
876 void operator()(ACX & x, const T & v)
877 {
878 V::operator()(x, v);
879 }
880 void operator()(const ACX & z, const ACX & x, const ACX & y)
881 {
882 V::operator()(z, x, y);
883 }
884 void call(ACX & x, const T & v, unsigned n)
885 {
886 V::call(x, v, n);
887 }
888 };
889 };
890
891 // polymorphic (conditional) tuple entry, modelled after cond_val
892 template <class ACX, class T, class Z, class V>
893 class tuple_entry
894 {
895 typedef typename Z::template load_type<ACX, T, V> load_type;
896 typedef load_type* ptr_type;
897
898 protected:
899 ptr_type p;
900
901 public:
902 tuple_entry() : p(0) {}
903 template <class TUPLE>
904 bool is_set(const TUPLE &) const { return p != 0; }
905
906 protected:
907 void make_load()
908 {
909 if (!p)
910 p = new load_type;
911 }
912 void assign(const V & v)
913 {
914 ptr_type tmp = new load_type(v);
915 delete p;
916 p = tmp;
917 }
918 void check_pointer() const
919 {
920 if (!p)
921 vigra_fail("tuple_entry::operator V &: unused tuple entry "
922 "type V = [" + std::string(typeid(V).name()) + "], "
923 "use set() to create an entry.");
924 }
925 public:
926 operator const V & () const
927 {
928 check_pointer();
929 return *p;
930 }
931 operator V & ()
932 {
933 check_pointer();
934 return *p;
935 }
936
937 template <class TUPLE> // not neccearily identical to ACX
938 void set(TUPLE & tuple)
939 {
940 make_load();
941 }
942 template <class TUPLE>
943 void set(const V & v, TUPLE & tuple)
944 {
945 set(tuple);
946 assign(v);
947 }
948
949 tuple_entry & operator=(tuple_entry const & e)
950 {
951 ptr_type tmp = new load_type(*e.p);
952 delete p;
953 p = tmp;
954 return *this;
955 }
956 tuple_entry(tuple_entry const & e)
957 : p(0)
958 {
959 if (e.p) // properly care for empty original
960 p = new load_type(*e.p);
961 }
962 ~tuple_entry()
963 {
964 delete p;
965 }
966 friend std::ostream & operator<<(std::ostream & os,
967 const tuple_entry & x)
968 {
969 if (x.p)
970 os << x.val(x);
971 else
972 os << "<nil>";
973 return os;
974 }
975 };
976
977 // pos is the position of type V in the type list of the tuple
978 template <class ACX, class T, class Z, class V, unsigned pos>
979 struct cond_tuple_entry : public tuple_entry<ACX, T, Z, V>
980 {
981 template <class TUPLE> // not quite identical to ACX
982 void set(TUPLE & tuple)
983 {
984 this->make_load();
985 tuple.template add<V>(this->p, pos);
986 }
987 template <class TUPLE>
988 void reassign(TUPLE & tuple)
989 {
990 if (this->p)
991 tuple.reassign(this->p, pos);
992 }
993 template <class TUPLE>
994 void set(const V & v, TUPLE & tuple)
995 {
996 set(tuple);
997 this->assign(v);
998 }
999 };
1000
1001 // helper classes for tuples
1002
1003 template <unsigned pos, class X>
1004 struct at_finder
1005 {
1006 typedef at_finder<pos - 1, typename X::rest_type> next_type;
1007 typedef typename next_type::type type;
1008 static
1009 type & at(X & x)
1010 {
1011 return next_type::at(x.rest);
1012 }
1013 };
1014 template <class X>
1015 struct at_finder<0, X>
1016 {
1017 typedef typename X::first_type type;
1018 static
1019 type & at(X & x) {
1020 return x.first;
1021 }
1022 };
1023
1024 template <class T, class X>
1025 struct sub_finder
1026 {
1027 typedef typename X::rest_type rest_type;
1028 typedef sub_finder<T, rest_type>
1029 next_type;
1030 typedef typename next_type::type type;
1031 static type & object(X & x)
1032 {
1033 return next_type::object(x.rest);
1034 }
1035 static const type & const_object(const X & x)
1036 {
1037 return next_type::const_object(x.rest);
1038 }
1039 };
1040 template <class X>
1041 struct sub_finder<typename X::finder_type, X>
1042 {
1043 typedef X type;
1044 static type & object(X & x)
1045 {
1046 return x;
1047 }
1048 static const type & const_object(const X & x)
1049 {
1050 return x;
1051 }
1052 };
1053
1054 template <class T, class X>
1055 struct ref_finder
1056 {
1057 typedef sub_finder<T, X> finder;
1058 typedef typename finder::type::first_type type;
1059 static
1060 type & ref(X & x)
1061 {
1062 return finder::object(x).first;
1063 }
1064 static
1065 const type & ref(const X & x)
1066 {
1067 return finder::const_object(x).first;
1068 }
1069 };
1070
1071 struct binder_0
1072 {
1073 template <class F>
1074 void operator()(F & first)
1075 {
1076 first();
1077 }
1078 template <class F>
1079 void call(F & first)
1080 {
1081 first.call();
1082 }
1083 };
1084 template <class A>
1085 struct binder_1
1086 {
1087 A v;
1088 binder_1(A v_) : v(v_) {}
1089 template <class F>
1090 void operator()(F & first)
1091 {
1092 first(v);
1093 }
1094 template <class F>
1095 void call(F & first)
1096 {
1097 first.call(v);
1098 }
1099 };
1100 template <class A, class B>
1101 struct binder_2
1102 {
1103 A v;
1104 B w;
1105 binder_2(A v_, B w_) : v(v_), w(w_) {}
1106 template <class F>
1107 void operator()(F & first)
1108 {
1109 first(v, w);
1110 }
1111 template <class F>
1112 void call(F & first)
1113 {
1114 first.call(v, w);
1115 }
1116 };
1117 template <class A, class B, class C>
1118 struct binder_3
1119 {
1120 A v;
1121 B w;
1122 C x;
1123 binder_3(A v_, B w_, C x_) : v(v_), w(w_), x(x_) {}
1124 template <class F>
1125 void operator()(F & first)
1126 {
1127 first(v, w, x);
1128 }
1129 template <class F>
1130 void call(F & first)
1131 {
1132 first.call(v, w, x);
1133 }
1134 };
1135
1136 // mechanism for iterative application of operator() to a tuple
1137 template <template <class> class TEST>
1138 struct exec_op_plain
1139 {
1140 template <class TUPLE, class B, class TBASE>
1141 static void exec(TUPLE & tuple, B & binder, const TBASE & z)
1142 {
1143 binder(tuple.first);
1144 tuple.rest.exec_bound_op(binder, z);
1145 }
1146 template <class TUPLE, class B, class TBASE>
1147 static void call(TUPLE & tuple, B & binder, const TBASE & z)
1148 {
1149 typedef typename TUPLE::ref_finder_type ref_finder_type;
1150 if (TEST<ref_finder_type>::value)
1151 binder.call(static_cast<ref_finder_type &> (tuple.first));
1152 tuple.rest.call_bound_op(binder, z);
1153 }
1154 };
1155
1156 // policy classes for tuples
1157 struct plain_global_data
1158 {
1159 void reassign() {}
1160 };
1161
1162 struct plain_chooser // this policy does effectively nothing.
1163 {
1164 template <class V, unsigned pos = 0>
1165 struct use
1166 {
1167 typedef V type;
1168 };
1169
1170 template <class, template <class> class TEST>
1171 struct exec_op : public exec_op_plain<TEST> {};
1172
1173 // "M" & "S" -> bug in cl.exe's parser.
1174 template <template<class, class, template<class> class M, unsigned>
1175 class, class, template<class> class S, unsigned>
1176 struct global_data : public plain_global_data
1177 {
1178 typedef global_data global_data_type;
1179 };
1180 template <class QV, class TUPLE>
1181 static bool is_set(const QV &, const TUPLE &) { return true; }
1182 template <class QV, class TUPLE>
1183 static void set(QV &, TUPLE &) {}
1184 };
1185
1186 // this policy uses the cond_val template to annotate
1187 // each tuple member with a bool that steers conditional
1188 // execution of each member's operator(), if called via
1189 // the tuple's operator().
1190 struct cond_chooser_plain : public plain_chooser
1191 {
1192 template <class V, unsigned pos = 0>
1193 struct use
1194 {
1195 typedef cond_val<V, pos> type;
1196 };
1197
1198 template <class, template <class> class TEST>
1199 struct exec_op
1200 {
1201 template <class TUPLE, class B, class TBASE>
1202 static void exec(TUPLE & tuple, B & binder, const TBASE & z)
1203 {
1204 typedef typename TUPLE::ref_finder_type ref_finder_type;
1205 if (tuple.first.is_set(z))
1206 binder(static_cast<ref_finder_type &>(tuple.first));
1207 tuple.rest.exec_bound_op(binder, z);
1208 }
1209 template <class TUPLE, class B, class TBASE>
1210 static void call(TUPLE & tuple, B & binder, const TBASE & z)
1211 {
1212 typedef typename TUPLE::ref_finder_type ref_finder_type;
1213 if (TEST<ref_finder_type>::value)
1214 if (tuple.first.is_set(z))
1215 binder.call(static_cast<ref_finder_type &>
1216 (tuple.first));
1217 tuple.rest.call_bound_op(binder, z);
1218 }
1219 };
1220
1221 template <class QV, class TUPLE>
1222 static bool is_set(const QV & qv, const TUPLE & t)
1223 {
1224 return qv.is_set(t);
1225 }
1226 template <class QV, class TUPLE>
1227 static void set(QV & qv, TUPLE & t)
1228 {
1229 qv.set(t);
1230 }
1231 };
1232
1233 // start the machinery for cond_chooser that produces nested 'if's
1234
1235 template <class X, class T, class L = typename get_pure_depends_on<T>::type>
1236 struct depends_on_deep
1237 {
1238 static const bool value =
1239 depends_on_deep<X, T, typename L::rest>::value // iterate list
1240 || depends_on_deep<X, typename L::first>::value; // indirect dep.
1241 };
1242 template <class T, class L>
1243 struct depends_on_deep<typename L::first, T, L>
1244 {
1245 static const bool value = true;
1246 };
1247 template <class X, class T>
1248 struct depends_on_deep<X, T, nil>
1249 {
1250 static const bool value = false;
1251 };
1252
1253 template <class T, class R>
1254 struct first_depends_on
1255 {
1256 static const bool value
1257 = depends_on_deep<typename R::first, T>::value;
1258 };
1259 template <class T>
1260 struct first_depends_on<T, nil>
1261 {
1262 static const bool value = false;
1263 };
1264
1265 template <class RRL, class R>
1266 struct first_depends_on_all_of
1267 {
1268 static const bool value
1269 = ChooseBool<
1270 first_depends_on<typename
1271 RRL::first,
1272 R
1273 >,
1274 first_depends_on_all_of<typename RRL::rest, R>,
1275 VigraFalseType
1276 >::value;
1277 };
1278 template <class R> // end of list RRL: 'success'
1279 struct first_depends_on_all_of<nil, R>
1280 {
1281 static const bool value = true;
1282 };
1283 template <class RRL> // 'invalid' input (e.g., at end of cond_op recursion)
1284 struct first_depends_on_all_of<RRL, nil>
1285 {
1286 static const bool value = false;
1287 };
1288 template <> // 'invalid' input (e.g., at end of cond_op recursion)
1289 struct first_depends_on_all_of<nil, nil>
1290 {
1291 static const bool value = false;
1292 };
1293
1294 // helper structs for cond_op:
1295 struct null_exec
1296 {
1297 template <class TUPLE, class B, class TBASE>
1298 static void exec(TUPLE &, B &, const TBASE &) {}
1299 template <class TUPLE, class B, class TBASE>
1300 static void call(TUPLE &, B &, const TBASE &) {}
1301 typedef nil iter_leftover_type;
1302 };
1303 template <bool cond, class EX>
1304 struct if_then
1305 {
1306 template <class TUPLE, class B, class TBASE>
1307 static void exec(TUPLE & t, B & b, const TBASE & z)
1308 {
1309 IfBool<cond, EX, null_exec>::type::exec(t, b, z);
1310 }
1311 template <class TUPLE, class B, class TBASE>
1312 static void call(TUPLE & t, B & b, const TBASE & z)
1313 {
1314 IfBool<cond, EX, null_exec>::type::call(t, b, z);
1315 }
1316 };
1317 template <class ZL, template <class> class TEST, class RRL>
1318 struct cond_op_inner;
1319
1320 template <class ZL, template <class> class TEST, class RRL = nil>
1321 struct cond_op
1322 {
1323 typedef typename ZL::first first_type;
1324 typedef typename ZL::rest rest_type;
1325 typedef cons<first_type, RRL> next_rr_list;
1326
1327 static const bool recurse_deep
1328 = first_depends_on<first_type, rest_type>::value;
1329 typedef cond_op<rest_type, TEST, next_rr_list>
1330 deep_type;
1331
1332 typedef typename IfBool<recurse_deep, typename
1333 deep_type::iter_leftover_type,
1334 rest_type
1335 >::type
1336 deep_leftover_type;
1337
1338 static const bool iterate
1339 = first_depends_on_all_of<RRL, deep_leftover_type>::value;
1340
1341 typedef cond_op_inner<deep_leftover_type, TEST, RRL>
1342 iter_type;
1343
1344 // the type list left over from the deep first recursion of exec()
1345 // and the iteration step: the recursion patterns of both the type
1346 // 'iter_leftover_type' and the function 'exec()' must match.
1347 typedef typename IfBool<iterate, typename
1348 iter_type::iter_leftover_type,
1349 deep_leftover_type
1350 >::type
1351 iter_leftover_type;
1352
1353 // the code generation templates
1354 template <class TUPLE, class B, class TBASE>
1355 static void exec(TUPLE & tuple, B & binder, const TBASE & z)
1356 {
1357 if (tuple.first.is_set(z))
1358 {
1359 binder(tuple.first);
1360 if_then<recurse_deep, deep_type>::exec(tuple.rest, binder, z);
1361 }
1362 if_then<iterate, iter_type>::exec(tuple, binder, z);
1363 }
1364 template <class TUPLE, class B, class TBASE>
1365 static void call(TUPLE & tuple, B & binder, const TBASE & z)
1366 {
1367 if (tuple.first.is_set(z))
1368 {
1369 typedef typename TUPLE::ref_finder_type ref_finder_type;
1370 if (TEST<ref_finder_type>::value)
1371 binder.call(static_cast<ref_finder_type &> (tuple.first));
1372
1373 if_then<recurse_deep, deep_type>::call(tuple.rest, binder, z);
1374 }
1375 if_then<iterate, iter_type>::call(tuple, binder, z);
1376 }
1377 };
1378 template <template <class> class TEST, class RRL> // end of type list ZL
1379 struct cond_op<nil, TEST, RRL> : public null_exec {};
1380
1381 template <template <class> class TEST, class RRL> // end of type list ZL
1382 struct cond_op_inner<nil, TEST, RRL> : public null_exec {};
1383
1384 template <class ZL, template <class> class TEST, class RRL>
1385 struct cond_op_inner
1386 {
1387 typedef cond_op<ZL, TEST, RRL> exec_type;
1388 typedef typename exec_type::iter_leftover_type iter_leftover_type;
1389
1390 template <class TUPLE, class B, class TBASE>
1391 static void exec(TUPLE & tuple, B & binder, const TBASE & z)
1392 {
1393 exec_type::
1394 exec(sub_finder<typename ZL::first, TUPLE>::object(tuple),
1395 binder,
1396 z);
1397 }
1398 template <class TUPLE, class B, class TBASE>
1399 static void call(TUPLE & tuple, B & binder, const TBASE & z)
1400 {
1401 exec_type::
1402 call(sub_finder<typename ZL::first, TUPLE>::object(tuple),
1403 binder,
1404 z);
1405 }
1406 };
1407
1408 struct cond_chooser : public cond_chooser_plain
1409 {
1410 template <class ZL, template <class> class TEST>
1411 struct exec_op : public cond_op<ZL, TEST> {};
1412 };
1413
1414 struct bit_cond_chooser : public cond_chooser
1415 {
1416 template <class V, unsigned pos>
1417 struct use
1418 {
1419 typedef bit_cond_val<V, pos> type;
1420 };
1421
1422 // cl.exe wants this -- maybe it is right.
1423 template <template<class, class, template<class> class M, unsigned>
1424 class, class, template<class> class S, unsigned>
1425 struct global_data : public plain_global_data
1426 {
1427 typedef global_data global_data_type;
1428 };
1429 template <template<class, class, template<class> class M, unsigned>
1430 class TBASE, class ITL, template<class> class TEST>
1431 struct global_data<TBASE, ITL, TEST, 0> : public plain_global_data
1432 {
1433 // typedef to catch our copy constructor and assignment operator:
1434 typedef global_data global_data_type;
1435
1436 BitArray<size<ITL>::of> bit_set;
1437
1438 void clear() { bit_set.clear(); }
1439 template <unsigned pos>
1440 void set_bit() { bit_set.template set<pos>(); }
1441 template <unsigned pos>
1442 bool is_bit_set() const { return bit_set.template test<pos>(); }
1443 };
1444 };
1445
1446 template <class ACX, class T, class Z>
1447 struct virtual_chooser: public cond_chooser_plain
1448 {
1449 template <class V, unsigned pos = 0>
1450 struct use
1451 {
1452 typedef tuple_entry<ACX, T, Z, V> type;
1453 };
1454 };
1455
1456 template <class T> struct set_exec
1457 {
1458 template <class ACX>
1459 static void exec(ACX & x)
1460 {
1461 x.template set<T>();
1462 }
1463 };
1464
1465 template <class ACX, class T, class Z>
1466 struct cond_virtual_chooser: public cond_chooser_plain
1467 {
1468 template <class V, unsigned pos = 0>
1469 struct use
1470 {
1471 typedef cond_tuple_entry<ACX, T, Z, V, pos> type;
1472 };
1473
1474 template <class, template <class> class TEST>
1475 struct exec_op
1476 {
1477 template <class TUPLE, class B, class TBASE>
1478 static void exec(TUPLE & tuple, B & binder, const TBASE &)
1479 {
1480 for (unsigned i = 0; i != tuple.execs.size; ++i)
1481 binder(*tuple.execs.pointers[i]);
1482 }
1483 template <class TUPLE, class B, class TBASE>
1484 static void call(TUPLE & tuple, B & binder, const TBASE &)
1485 {
1486 for (unsigned i = 0; i != tuple.callers.size; ++i)
1487 binder.call(*tuple.callers.pointers[i]);
1488 }
1489 };
1490 // cl.exe wants this -- maybe it is right.
1491 template <template<class, class, template<class> class M, unsigned>
1492 class, class, template<class> class S, unsigned>
1493 struct global_data : public plain_global_data
1494 {
1495 typedef global_data global_data_type;
1496 };
1497
1498 template <class ITL>
1499 struct global_data_pointers // weak pointers
1500 {
1501 typedef typename Z::template member_base_type<ACX, T>* pointer_type;
1502 static const unsigned array_len = size<ITL>::of;
1503
1504 unsigned orders [array_len]; // consciously use two arrays
1505 unsigned size;
1506 pointer_type pointers[array_len];
1507
1508 void clear()
1509 {
1510 size = 0;
1511 }
1512 global_data_pointers()
1513 {
1514 clear();
1515 }
1516 unsigned* end(unsigned* = 0)
1517 {
1518 return orders + size;
1519 }
1520 pointer_type* end(pointer_type*)
1521 {
1522 return pointers + size;
1523 }
1524 template <class E>
1525 void make_room(E* i)
1526 {
1527 std::copy_backward(i, end(i), end(i) + 1);
1528 }
1529 typedef std::pair<unsigned*, pointer_type*> finder;
1530 bool find(unsigned pos, finder & found)
1531 {
1532 found.first = std::lower_bound(orders, end(), pos);
1533 found.second = pointers + (found.first - orders);
1534 return found.first != end() && *found.first == pos;
1535 }
1536 void add(pointer_type p, unsigned pos)
1537 {
1538 // merge pointer according to its topological sort order
1539 finder found;
1540 if (find(pos, found))
1541 return;
1542 make_room(found.first);
1543 make_room(found.second);
1544 ++size;
1545 *found.first = pos;
1546 *found.second = p;
1547 }
1548 void reassign(pointer_type p, unsigned pos)
1549 {
1550 // replace pointers -- the present values still belong to
1551 // the old tuple object that was copied from
1552 finder found;
1553 if (find(pos, found))
1554 *found.second = p;
1555 }
1556 };
1557 template <template<class, class, template<class> class M, unsigned>
1558 class TBASE, class ITL, template<class> class TEST>
1559 struct global_data<TBASE, ITL, TEST, 0>
1560 {
1561 // typedef to catch our copy constructor and assignment operator:
1562 typedef global_data global_data_type;
1563 // the derived class:
1564 typedef TBASE<ITL, cond_virtual_chooser, TEST, 0> crtp_type;
1565
1566 typedef global_data_pointers<ITL> ptrs_type;
1567 typedef typename ptrs_type::pointer_type pointer_type;
1568 ptrs_type callers;
1569 ptrs_type execs;
1570
1571 template <class V>
1572 void add(pointer_type p, unsigned pos)
1573 {
1574 execs.add(p, pos);
1575 if (TEST<V>::value)
1576 callers.add(p, pos);
1577 }
1578 void reassign(pointer_type p, unsigned pos)
1579 {
1580 execs. reassign(p, pos);
1581 callers.reassign(p, pos);
1582 }
1583
1584 template <class V>
1585 struct reassign_op
1586 {
1587 static void exec(crtp_type & tuple)
1588 {
1589 tuple.template ref<V>().reassign(tuple);
1590 }
1591 };
1592
1593 void reassign()
1594 {
1595 for_all<ITL, reassign_op>(static_cast<crtp_type &>(*this));
1596 }
1597 };
1598 };
1599
1600
1601 template <class ITL, class Q = plain_chooser,
1602 template<class> class TEST = true_test, unsigned index = 0>
1603 struct tuple_base
1604 : public Q::template global_data<tuple_base, ITL, TEST, index>
1605 {
1606 typedef typename tuple_base::global_data_type global_data_base_type;
1607 typedef nil derived_type; // dummy declaration for static_cast_2<>
1608 typedef tuple_base tuple_type;
1609 typedef ITL list_type;
1610
1611 // use the original types from the list to find tuple members via ref():
1612 typedef typename ITL::first finder_type;
1613 typedef typename ITL::rest rest_list_type;
1614
1615 typedef tuple_base<rest_list_type, Q, TEST, index + 1> rest_type;
1616
1617 // use policy class Q to annotate the types of the type list ITL
1618 // for use as members of the tuple:
1619 // -- the actually stored type
1620 typedef typename ITL::first ref_finder_type;
1621 typedef typename Q::template use<ref_finder_type,
1622 index>::type first_type;
1623 first_type first;
1624 rest_type rest;
1625
1626 template <class T>
1627 struct has_element
1628 {
1629 static const bool value = contains<T, ITL>::value;
1630 };
1631
1632 template <unsigned pos>
1633 typename at_finder<pos, tuple_base>::type & at()
1634 {
1635 return at_finder<pos, tuple_base>::at(*this);
1636 }
1637
1638 template <class T>
1639 struct ref_returns
1640 {
1641 typedef ref_finder<T, tuple_base> finder;
1642 typedef typename finder::type ref_finder_type;
1643 typedef ref_finder_type & type;
1644 typedef const ref_finder_type & const_type;
1645 };
1646 template <class T>
1647 typename ref_returns<T>::type
1648 ref()
1649 {
1650 return ref_returns<T>::finder::ref(*this);
1651 }
1652 template <class T>
1653 typename ref_returns<T>::const_type
1654 ref() const
1655 {
1656 return ref_returns<T>::finder::ref(*this);
1657 }
1658
1659 template <class V>
1660 bool is_set() const
1661 {
1662 return Q::template is_set(this->template ref<V>(), *this);
1663 }
1664 template <class RV>
1665 void set_if_not(RV & rv)
1666 {
1667 if (! Q::template is_set(rv, *this))
1668 Q::template set(rv, *this);
1669 }
1670 // recursively set all the cond_val::is_set bits of the depended-on
1671 // types, or, respectively, take equivalent action.
1672 template <class V>
1673 void set()
1674 {
1675 set_if_not(this->template ref<V>());
1676 for_all_used<V, set_exec>(*this);
1677 }
1678 // transfer the set bits of *this to another tuple t2:
1679 // (ITL must be a subset of ITL2.)
1680 template <class ITL2, class Q2, template<class> class TEST2>
1681 void transfer_set_to(tuple_base<ITL2, Q2, TEST2> & t2) const
1682 {
1683 if (is_set<ref_finder_type>())
1684 t2.template set<ref_finder_type>();
1685 rest.transfer_set_to(t2);
1686 }
1687
1688 // policy-based application of operator()
1689 template <class B, class TBASE>
1690 void exec_bound_op(B & binder, const TBASE & z)
1691 {
1692 Q::template exec_op<list_type, true_test>::exec(*this, binder, z);
1693 }
1694 template <class B>
1695 void exec_bound(B & binder)
1696 {
1697 exec_bound_op(binder, *this);
1698 }
1699
1700 void operator()()
1701 {
1702 binder_0 binder;
1703 exec_bound(binder);
1704 }
1705
1706 template <class A>
1707 void operator()(const A & v)
1708 {
1709 binder_1<const A &> binder(v);
1710 exec_bound(binder);
1711 }
1712 template <class A>
1713 void operator()(A & v)
1714 {
1715 binder_1<A &> binder(v);
1716 exec_bound(binder);
1717 }
1718 template <class A>
1719 void operator()(A & v) const
1720 {
1721 binder_1<A &> binder(v);
1722 exec_bound(binder);
1723 }
1724
1725 template <class A, class B>
1726 void operator()(const A & v, const B & w)
1727 {
1728 binder_2<const A &, const B &> binder(v, w);
1729 exec_bound(binder);
1730 }
1731 template <class A, class B>
1732 void operator()(A & v, const B & w)
1733 {
1734 binder_2<A &, const B &> binder(v, w);
1735 exec_bound(binder);
1736 }
1737 template <class A, class B>
1738 void operator()(A & v, const B & w) const
1739 {
1740 binder_2<A &, const B &> binder(v, w);
1741 exec_bound(binder);
1742 }
1743
1744 template <class A, class B, class C>
1745 void operator()(const A & v, const B & w, const C & x)
1746 {
1747 binder_3<const A &, const B &, const C &> binder(v, w, x);
1748 exec_bound(binder);
1749 }
1750 template <class A, class B, class C>
1751 void operator()(A & v, const B & w, const C & x)
1752 {
1753 binder_3<A &, const B &, const C &> binder(v, w, x);
1754 exec_bound(binder);
1755 }
1756 template <class A, class B, class C>
1757 void operator()(A & v, const B & w, const C & x) const
1758 {
1759 binder_3<A &, const B &, const C &> binder(v, w, x);
1760 exec_bound(binder);
1761 }
1762
1763 // policy-based application of call()
1764 template <class B, class TBASE>
1765 void call_bound_op(B & binder, const TBASE & z)
1766 {
1767 Q::template exec_op<list_type, TEST>::call(*this, binder, z);
1768 }
1769 template <class B>
1770 void call_bound(B & binder)
1771 {
1772 call_bound_op(binder, *this);
1773 }
1774
1775 template <class A, class B>
1776 void call(const A & v, const B & w)
1777 {
1778 binder_2<const A &, const B &> binder(v, w);
1779 call_bound(binder);
1780 }
1781 template <class A, class B>
1782 void call(A & v, const B & w)
1783 {
1784 binder_2<A &, const B &> binder(v, w);
1785 call_bound(binder);
1786 }
1787 template <class A, class B>
1788 void call(A & v, const B & w) const
1789 {
1790 binder_2<A &, const B &> binder(v, w);
1791 call_bound(binder);
1792 }
1793
1794 template <class A, class B, class C>
1795 void call(const A & v, const B & w, const C & x)
1796 {
1797 binder_3<const A &, const B &, const C &> binder(v, w, x);
1798 call_bound(binder);
1799 }
1800 template <class A, class B, class C>
1801 void call(A & v, const B & w, const C & x)
1802 {
1803 binder_3<A &, const B &, const C &> binder(v, w, x);
1804 call_bound(binder);
1805 }
1806 template <class A, class B, class C>
1807 void call(A & v, const B & w, const C & x) const
1808 {
1809 binder_3<A &, const B &, const C &> binder(v, w, x);
1810 call_bound(binder);
1811 }
1812
1813 // the possible reassign() of global data requires handmade copies here
1814 tuple_base() {}
1815 tuple_base(const tuple_base & x)
1816 : global_data_base_type(x), first(x.first), rest(x.rest)
1817 {
1818 this->reassign();
1819 }
1820 tuple_base & operator=(const tuple_base & x)
1821 {
1822 global_data_base_type::operator=(x);
1823 first = x.first;
1824 rest = x.rest;
1825 this->reassign();
1826 return *this;
1827 }
1828 };
1829 template <class Q, template <class> class TEST, unsigned index>
1830 struct tuple_base<nil, Q, TEST, index>
1831 {
1832 template <class>
1833 struct has_element
1834 {
1835 static const bool value = false;
1836 };
1837 template <class B, class TBASE>
1838 void exec_bound_op(B &, const TBASE &) {}
1839 template <class B, class TBASE>
1840 void call_bound_op(B &, const TBASE &) {}
1841 template <class ITL2, class Q2, template<class> class TEST2>
1842 void transfer_set_to(tuple_base<ITL2, Q2, TEST2> &) const {}
1843 };
1844
1845 template <class V, class L, class A, class B>
1846 struct choose_tuple
1847 {
1848 static const bool value = contains<V, L>::value;
1849 typedef typename IfBool<value, A, B>::type type;
1850 static type & at(A & a, B & b)
1851 {
1852 return choose_type<value>::at(a, b);
1853 }
1854 static const type & at(const A & a, const B & b)
1855 {
1856 return choose_type<value>::at(a, b);
1857 }
1858
1859 typedef typename type::template ref_returns<V>:: type
1860 ref_type;
1861 typedef typename type::template ref_returns<V>::const_type
1862 const_ref_type;
1863
1864 ref_type
1865 static ref(A & a, B & b)
1866 {
1867 return at(a, b).template ref<V>();
1868 }
1869 const_ref_type
1870 static ref(const A & a, const B & b)
1871 {
1872 return at(a, b).template ref<V>();
1873 }
1874 };
1875
1876 template <class ITL, template<class> class TEST = true_test>
1877 struct tuple : public tuple_base<ITL, plain_chooser, TEST> {};
1878
1879 template <class ITL, template<class> class TEST = true_test>
1880 struct cond_tuple_plain
1881 : public tuple_base<ITL, cond_chooser_plain, TEST> {};
1882
1883 template <class ITL, template<class> class TEST = true_test>
1884 struct cond_tuple : public tuple_base<ITL, cond_chooser, TEST> {};
1885
1886 template <class ITL, template<class> class TEST = true_test>
1887 struct bit_cond_tuple : public tuple_base<ITL, bit_cond_chooser, TEST> {};
1888
1889 template <class ITL, class ACX, class T, class Z,
1890 template<class> class TEST = true_test>
1891 struct virtual_tuple_base
1892 : public tuple_base<ITL, virtual_chooser<ACX, T, Z>, TEST> {};
1893
1894 template <template <class, class> class ACXTT, class T,
1895 class Z = simple_member_dispatch>
1896 struct virtual_tuple
1897 {
1898 template <class ITL, template<class> class TEST = true_test>
1899 struct type
1900 : public virtual_tuple_base<ITL, ACXTT<T, ITL>, T, Z, TEST> {};
1901 };
1902
1903 template <class ITL, class ACX, class T, class Z,
1904 template<class> class TEST = true_test>
1905 struct cond_virtual_tuple_base
1906 : public tuple_base<ITL, cond_virtual_chooser<ACX, T, Z>, TEST>
1907 {
1908 typedef ACX derived_type;
1909 };
1910
1911 template <template <class, class> class ACXTT, class T,
1912 class Z = simple_member_dispatch>
1913 struct cond_virtual_tuple
1914 {
1915 template <class ITL, template<class> class TEST = true_test>
1916 struct type
1917 : public cond_virtual_tuple_base<ITL, ACXTT<T, ITL>, T, Z, TEST> {};
1918 };
1919
1920 } // namespace type_lists
1921
1922 // mask cl.exe shortcomings [end]
1923 #if defined(_MSC_VER)
1924 #pragma warning( pop )
1925 #endif
1926
1927 } // namespace vigra
1928
1929 #endif // VIGRA_TYPE_LISTS_HXX
vigra::add
void add(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
addition with enforced result type.
Definition: fixedpoint.hxx:561
vigra
Definition: accessor.hxx:43
std::operator<<
ostream & operator<<(ostream &s, const vigra::MultiArrayView< 2, T, C > &m)
Definition: matrix.hxx:2322
vigra::reverse
TinyVector< V, SIZE > reverse(TinyVector< V, SIZE > const &t)
reversed copy
Definition: tinyvector.hxx:2037

© 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