[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/type_lists.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2011-2012 by Markus Nullmeier and Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef VIGRA_TYPE_LISTS_HXX 00037 #define VIGRA_TYPE_LISTS_HXX 00038 00039 #include <iostream> 00040 #include <typeinfo> 00041 #include <utility> 00042 #include <algorithm> 00043 #include "metaprogramming.hxx" 00044 #include "bit_array.hxx" 00045 #include "error.hxx" 00046 00047 namespace vigra { 00048 00049 // mask cl.exe shortcomings [begin] 00050 #if defined(_MSC_VER) 00051 #pragma warning( push ) 00052 #pragma warning( disable : 4503 ) 00053 #endif 00054 00055 namespace type_lists { 00056 00057 struct nil; // end-of-list marker. 00058 template <class T> 00059 struct nil_t; 00060 00061 // type lists of size >= 1. 00062 00063 template <class A, class B = nil> struct cons 00064 { 00065 typedef A first; 00066 typedef B rest; 00067 }; 00068 00069 template <class X, class A, class B> struct if_nil 00070 { 00071 typedef B type; 00072 }; 00073 template <class A, class B> struct if_nil <nil, A, B> 00074 { 00075 typedef A type; 00076 }; 00077 00078 // truncate type list L (using class NIL as ending marker) 00079 // at the first occurence of type X 00080 template <class X, class L, class NIL = nil> struct truncate 00081 { 00082 typedef cons<typename L::first, 00083 typename truncate<X, typename L::rest, NIL>::type> type; 00084 }; 00085 template <class L, class NIL> struct truncate<typename L::first, L, NIL> 00086 { 00087 typedef nil type; // do the actual truncation 00088 }; 00089 template <class X, class NIL> struct truncate<X, NIL, NIL> 00090 { 00091 typedef nil type; 00092 }; 00093 00094 template <class NIL, class A = NIL, class B = NIL, class C = NIL, 00095 class D = NIL, class E = NIL, class F = NIL, 00096 class G = NIL, class H = NIL, class I = NIL, 00097 class J = NIL, class K = NIL, class L = NIL, 00098 class M = NIL, class N = NIL, class O = NIL, 00099 class P = NIL, class Q = NIL, class R = NIL, 00100 class S = NIL, class T = NIL, class U = NIL, 00101 class V = NIL, class W = NIL, class X = NIL, 00102 class Y = NIL, class Z = NIL> 00103 struct make_list_nil { 00104 typedef typename truncate<NIL, cons<A, cons<B, cons<C, cons<D, cons<E, 00105 cons<F, cons<G, cons<H, cons<I, cons<J, 00106 cons<K, cons<L, cons<M, cons<N, cons<O, 00107 cons<P, cons<Q, cons<R, cons<S, cons<T, 00108 cons<U, cons<V, cons<W, cons<X, cons<Y, 00109 cons<Z, NIL> > > > > > > > > > > > > > > 00110 > > > > > > > > > > >, NIL>::type type; 00111 }; 00112 00113 template <class A = nil, class B = nil, class C = nil, class D = nil, 00114 class E = nil, class F = nil, class G = nil, class H = nil, 00115 class I = nil, class J = nil, class K = nil, class L = nil, 00116 class M = nil, class N = nil, class O = nil, class P = nil, 00117 class Q = nil, class R = nil, class S = nil, class T = nil, 00118 class U = nil, class V = nil, class W = nil, class X = nil, 00119 class Y = nil, class Z = nil> 00120 00121 struct make_list { 00122 typedef typename make_list_nil<nil, A, B, C, D, E, F, G, H, I, 00123 J, K, L, M, N, O, P, Q, R, 00124 S, T, U, V, W, X, Y, Z 00125 >::type type; 00126 }; 00127 00128 template <class T_, template<class> class A = nil_t, 00129 template<class> class B = nil_t, 00130 template<class> class C = nil_t, 00131 template<class> class D = nil_t, 00132 template<class> class E = nil_t, 00133 template<class> class F = nil_t, 00134 template<class> class G = nil_t, 00135 template<class> class H = nil_t, 00136 template<class> class I = nil_t, 00137 template<class> class J = nil_t, 00138 template<class> class K = nil_t, 00139 template<class> class L = nil_t, 00140 template<class> class M = nil_t, 00141 template<class> class N = nil_t, 00142 template<class> class O = nil_t, 00143 template<class> class P = nil_t, 00144 template<class> class Q = nil_t, 00145 template<class> class R = nil_t, 00146 template<class> class S = nil_t, 00147 template<class> class T = nil_t, 00148 template<class> class U = nil_t, 00149 template<class> class V = nil_t, 00150 template<class> class W = nil_t, 00151 template<class> class X = nil_t, 00152 template<class> class Y = nil_t, 00153 template<class> class Z = nil_t> 00154 struct make_list_template { 00155 typedef typename make_list_nil<nil_t<T_>, 00156 A<T_>, B<T_>, C<T_>, D<T_>, E<T_>, 00157 F<T_>, G<T_>, H<T_>, I<T_>, J<T_>, 00158 K<T_>, L<T_>, M<T_>, N<T_>, O<T_>, 00159 P<T_>, Q<T_>, R<T_>, S<T_>, T<T_>, 00160 U<T_>, V<T_>, W<T_>, X<T_>, Y<T_>, 00161 Z<T_> >::type type; 00162 }; 00163 00164 // a means to partially compensate for the lack of templated typedefs. 00165 template <template<class, class> class BASE, class T_, 00166 template<class> class A = nil_t, 00167 template<class> class B = nil_t, 00168 template<class> class C = nil_t, 00169 template<class> class D = nil_t, 00170 template<class> class E = nil_t, 00171 template<class> class F = nil_t, 00172 template<class> class G = nil_t, 00173 template<class> class H = nil_t, 00174 template<class> class I = nil_t, 00175 template<class> class J = nil_t, 00176 template<class> class K = nil_t, 00177 template<class> class L = nil_t, 00178 template<class> class M = nil_t, 00179 template<class> class N = nil_t, 00180 template<class> class O = nil_t, 00181 template<class> class P = nil_t, 00182 template<class> class Q = nil_t, 00183 template<class> class R = nil_t, 00184 template<class> class S = nil_t, 00185 template<class> class T = nil_t, 00186 template<class> class U = nil_t, 00187 template<class> class V = nil_t, 00188 template<class> class W = nil_t, 00189 template<class> class X = nil_t, 00190 template<class> class Y = nil_t, 00191 template<class> class Z = nil_t> 00192 struct use_template_list 00193 : public BASE<T_, typename make_list_template<T_, A, B, C, D, E, F, G, 00194 H, I, J, K, L, M, N, 00195 O, P, Q, R, S, T, U, 00196 V, W, X, Y, Z>::type> 00197 {}; 00198 00199 // use first and rest only when possible: 00200 template <class T> 00201 struct has_first_rest : public sfinae_test<T, has_first_rest> 00202 { 00203 template <class U> 00204 has_first_rest(U*, typename U::first* = 0, typename U::rest* = 0); 00205 }; 00206 template <bool P, class A> 00207 struct cond_cons_rest; 00208 template <class A> 00209 struct cond_cons_rest<false, A> 00210 { 00211 typedef void* type; 00212 }; 00213 template <class A> 00214 struct cond_cons_rest<true, A> 00215 { 00216 typedef typename A::rest type; 00217 }; 00218 // test if a type is a list in the above sense. 00219 template <class A> struct is_list 00220 { 00221 static const bool value = is_list<typename 00222 cond_cons_rest<has_first_rest<A>::value, A>::type>::value; 00223 }; 00224 template <> struct is_list<nil> 00225 { 00226 static const bool value = true; 00227 }; 00228 template <> struct is_list<void*> 00229 { 00230 static const bool value = false; 00231 }; 00232 00233 template <class A> struct list_guard 00234 { 00235 typedef typename IfBool<is_list<A>::value, A, nil>::type type; 00236 }; 00237 00238 template <class A> struct size 00239 { 00240 static const unsigned of = size<typename A::rest>::of + 1; 00241 }; 00242 template <> struct size<nil> 00243 { 00244 static const unsigned of = 0; 00245 }; 00246 00247 template <class X, class L> struct append 00248 { 00249 typedef cons<typename L::first, 00250 typename append<X, typename L::rest>::type> type; 00251 }; 00252 template <class X> struct append<X, nil> 00253 { 00254 typedef cons<X, nil> type; 00255 }; 00256 template <> struct append<nil, nil> 00257 { 00258 typedef nil type; 00259 }; 00260 00261 template <class L, class R = nil> struct reverse 00262 { 00263 typedef typename reverse<typename L::rest, 00264 cons<typename L::first, R> >::type type; 00265 }; 00266 template <class R> struct reverse<nil, R> 00267 { 00268 typedef R type; 00269 }; 00270 00271 template <template<class> class P, class Q, class L> 00272 struct max_value 00273 { 00274 static const bool is_nil = false; 00275 static const Q first_value = P<typename L::first>::value; 00276 typedef max_value<P, Q, typename L::rest> rest_type; 00277 static const Q rest_value = rest_type::value; 00278 static const bool gt = first_value > rest_value || rest_type::is_nil; 00279 static const Q value = gt * first_value + !gt * rest_value; 00280 }; 00281 template <template<class> class P, class Q> 00282 struct max_value<P, Q, nil> 00283 { 00284 static const Q value = 0; 00285 static const bool is_nil = true; 00286 }; 00287 00288 // remove the all occurences of type X in type list L 00289 template <class X, class L> struct remove // recursion 00290 { 00291 typedef cons<typename L::first, 00292 typename remove<X, typename L::rest>::type> type; 00293 }; 00294 template <class L> struct remove<typename L::first, L> // actual removal 00295 { 00296 typedef typename remove<typename L::first, typename L::rest>::type type; 00297 }; 00298 template <class X> struct remove<X, nil> // list end 00299 { 00300 typedef nil type; 00301 }; 00302 00303 // remove the all occurences of type list L where predicate P equals value 00304 template <template<class> class P, class L, bool value = true> 00305 struct remove_if 00306 { 00307 typedef typename 00308 IfBool< 00309 value == P<typename L::first>::value, typename 00310 remove_if<P, typename L::rest, value>::type, 00311 cons<typename 00312 L::first, typename 00313 remove_if<P, typename L::rest, value>::type 00314 > 00315 >::type type; 00316 }; 00317 template <template<class> class P, bool value> 00318 struct remove_if<P, nil, value> 00319 { 00320 typedef nil type; 00321 }; 00322 00323 template <template<class> class P, class L> 00324 struct remove_if_not 00325 { 00326 typedef typename remove_if<P, L, false>::type type; 00327 }; 00328 00329 template <class X, class L> struct contains 00330 { 00331 static const bool value = contains<X, typename L::rest>::value; 00332 }; 00333 template <class L> struct contains<typename L::first, L> 00334 { 00335 static const bool value = true; 00336 }; 00337 template <class X> struct contains<X, nil> 00338 { 00339 static const bool value = false; 00340 }; 00341 00342 // simple, unstable merge 00343 template <class X, class L> struct merge 00344 { 00345 typedef typename L::first first; 00346 typedef typename 00347 merge< 00348 typename IfBool<contains<first, X>::value, 00349 X, 00350 cons<first, X> 00351 >::type, 00352 typename L::rest 00353 >::type type; 00354 }; 00355 template <class X> struct merge<X, nil> 00356 { 00357 typedef X type; 00358 }; 00359 00360 // simple, unstable unique 00361 template <class L> struct unique 00362 { 00363 typedef typename merge<nil, L>::type type; 00364 }; 00365 00366 template <class T_, template<class> class A = nil_t, 00367 template<class> class B = nil_t, 00368 template<class> class C = nil_t, 00369 template<class> class D = nil_t, 00370 template<class> class E = nil_t, 00371 template<class> class F = nil_t, 00372 template<class> class G = nil_t, 00373 template<class> class H = nil_t, 00374 template<class> class I = nil_t, 00375 template<class> class J = nil_t, 00376 template<class> class K = nil_t, 00377 template<class> class L = nil_t, 00378 template<class> class M = nil_t, 00379 template<class> class N = nil_t, 00380 template<class> class O = nil_t, 00381 template<class> class P = nil_t, 00382 template<class> class Q = nil_t, 00383 template<class> class R = nil_t, 00384 template<class> class S = nil_t, 00385 template<class> class T = nil_t, 00386 template<class> class U = nil_t, 00387 template<class> class V = nil_t, 00388 template<class> class W = nil_t, 00389 template<class> class X = nil_t, 00390 template<class> class Y = nil_t, 00391 template<class> class Z = nil_t> 00392 struct implies_template 00393 { 00394 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K, 00395 L, M, N, O, P, Q, R, S, T, U, V, 00396 W, X, Y, Z>::type implies_types; 00397 }; 00398 00399 template <class T_, template<class> class A = nil_t, 00400 template<class> class B = nil_t, 00401 template<class> class C = nil_t, 00402 template<class> class D = nil_t, 00403 template<class> class E = nil_t, 00404 template<class> class F = nil_t, 00405 template<class> class G = nil_t, 00406 template<class> class H = nil_t, 00407 template<class> class I = nil_t, 00408 template<class> class J = nil_t, 00409 template<class> class K = nil_t, 00410 template<class> class L = nil_t, 00411 template<class> class M = nil_t, 00412 template<class> class N = nil_t, 00413 template<class> class O = nil_t, 00414 template<class> class P = nil_t, 00415 template<class> class Q = nil_t, 00416 template<class> class R = nil_t, 00417 template<class> class S = nil_t, 00418 template<class> class T = nil_t, 00419 template<class> class U = nil_t, 00420 template<class> class V = nil_t, 00421 template<class> class W = nil_t, 00422 template<class> class X = nil_t, 00423 template<class> class Y = nil_t, 00424 template<class> class Z = nil_t> 00425 struct follows_template 00426 { 00427 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K, 00428 L, M, N, O, P, Q, R, S, T, U, V, 00429 W, X, Y, Z>::type follows_types; 00430 }; 00431 00432 template <class T_, template<class> class A = nil_t, 00433 template<class> class B = nil_t, 00434 template<class> class C = nil_t, 00435 template<class> class D = nil_t, 00436 template<class> class E = nil_t, 00437 template<class> class F = nil_t, 00438 template<class> class G = nil_t, 00439 template<class> class H = nil_t, 00440 template<class> class I = nil_t, 00441 template<class> class J = nil_t, 00442 template<class> class K = nil_t, 00443 template<class> class L = nil_t, 00444 template<class> class M = nil_t, 00445 template<class> class N = nil_t, 00446 template<class> class O = nil_t, 00447 template<class> class P = nil_t, 00448 template<class> class Q = nil_t, 00449 template<class> class R = nil_t, 00450 template<class> class S = nil_t, 00451 template<class> class T = nil_t, 00452 template<class> class U = nil_t, 00453 template<class> class V = nil_t, 00454 template<class> class W = nil_t, 00455 template<class> class X = nil_t, 00456 template<class> class Y = nil_t, 00457 template<class> class Z = nil_t> 00458 struct depends_on_template 00459 { 00460 typedef typename make_list_template<T_, A, B, C, D, E, F, G, H, I, J, K, 00461 L, M, N, O, P, Q, R, S, T, U, V, 00462 W, X, Y, Z>::type depends_on; 00463 }; 00464 00465 template <class T_u, template<class> class A = nil_t, 00466 template<class> class B = nil_t, 00467 template<class> class C = nil_t, 00468 template<class> class D = nil_t, 00469 template<class> class E = nil_t, 00470 template<class> class F = nil_t, 00471 template<class> class G = nil_t, 00472 template<class> class H = nil_t, 00473 template<class> class I = nil_t, 00474 template<class> class J = nil_t, 00475 template<class> class K = nil_t, 00476 template<class> class L = nil_t, 00477 template<class> class M = nil_t, 00478 template<class> class N = nil_t, 00479 template<class> class O = nil_t, 00480 template<class> class P = nil_t, 00481 template<class> class Q = nil_t, 00482 template<class> class R = nil_t, 00483 template<class> class S = nil_t, 00484 template<class> class T = nil_t, 00485 template<class> class U = nil_t, 00486 template<class> class V = nil_t, 00487 template<class> class W = nil_t, 00488 template<class> class X = nil_t, 00489 template<class> class Y = nil_t, 00490 template<class> class Z = nil_t> 00491 struct uses_template 00492 : public implies_template<T_u, A, B, C, D, E, F, G, H, I, J, K, L, M, 00493 N, O, P, Q, R, S, T, U, V, W, X, Y, Z>, 00494 public depends_on_template<T_u, A, B, C, D, E, F, G, H, I, J, K, L, M, 00495 N, O, P, Q, R, S, T, U, V, W, X, Y, Z> 00496 { 00497 template <template<class> class A_ = nil_t, 00498 template<class> class B_ = nil_t, 00499 template<class> class C_ = nil_t, 00500 template<class> class D_ = nil_t, 00501 template<class> class E_ = nil_t, 00502 template<class> class F_ = nil_t, 00503 template<class> class G_ = nil_t, 00504 template<class> class H_ = nil_t, 00505 template<class> class I_ = nil_t, 00506 template<class> class J_ = nil_t, 00507 template<class> class K_ = nil_t, 00508 template<class> class L_ = nil_t, 00509 template<class> class M_ = nil_t, 00510 template<class> class N_ = nil_t, 00511 template<class> class O_ = nil_t, 00512 template<class> class P_ = nil_t, 00513 template<class> class Q_ = nil_t, 00514 template<class> class R_ = nil_t, 00515 template<class> class S_ = nil_t, 00516 template<class> class T_ = nil_t, 00517 template<class> class U_ = nil_t, 00518 template<class> class V_ = nil_t, 00519 template<class> class W_ = nil_t, 00520 template<class> class X_ = nil_t, 00521 template<class> class Y_ = nil_t, 00522 template<class> class Z_ = nil_t> 00523 struct follows 00524 : public uses_template 00525 , public follows_template<T_u, A_, B_, C_, D_, E_, F_, G_, H_, I_, 00526 J_, K_, L_, M_, N_, O_, P_, Q_, R_, 00527 S_, T_, U_, V_, W_, X_, Y_, Z_> {}; 00528 00529 template <template<class> class A_ = nil_t, 00530 template<class> class B_ = nil_t, 00531 template<class> class C_ = nil_t, 00532 template<class> class D_ = nil_t, 00533 template<class> class E_ = nil_t, 00534 template<class> class F_ = nil_t, 00535 template<class> class G_ = nil_t, 00536 template<class> class H_ = nil_t, 00537 template<class> class I_ = nil_t, 00538 template<class> class J_ = nil_t, 00539 template<class> class K_ = nil_t, 00540 template<class> class L_ = nil_t, 00541 template<class> class M_ = nil_t, 00542 template<class> class N_ = nil_t, 00543 template<class> class O_ = nil_t, 00544 template<class> class P_ = nil_t, 00545 template<class> class Q_ = nil_t, 00546 template<class> class R_ = nil_t, 00547 template<class> class S_ = nil_t, 00548 template<class> class T_ = nil_t, 00549 template<class> class U_ = nil_t, 00550 template<class> class V_ = nil_t, 00551 template<class> class W_ = nil_t, 00552 template<class> class X_ = nil_t, 00553 template<class> class Y_ = nil_t, 00554 template<class> class Z_ = nil_t> 00555 struct implies 00556 : public uses_template 00557 { 00558 typedef typename 00559 merge<typename 00560 uses_template::implies_types, typename 00561 implies_template<T_u, A_, B_, C_, D_, E_, F_, G_, H_, I_, 00562 J_, K_, L_, M_, N_, O_, P_, Q_, R_, 00563 S_, T_, U_, V_, W_, X_, Y_, Z_> 00564 ::implies_types 00565 >::type 00566 implies_types; 00567 }; 00568 }; 00569 00570 // for_all() helper class. 00571 template <template<class> class EXEC, class L> struct for_exec 00572 { 00573 template <class TX> 00574 static void all(TX & tx) 00575 { 00576 EXEC<typename L::first>::exec(tx); 00577 for_exec<EXEC, typename L::rest>::all(tx); 00578 } 00579 }; 00580 template <template<class> class EXEC> struct for_exec<EXEC, nil> 00581 { 00582 template <class TX> static void all(TX &) {} 00583 }; 00584 // for_all on type lists. 00585 // for all types T in the list L, 00586 // calls the static member function EXEC<T>::exec(TX & tx). 00587 template <class L, template<class> class EXEC, class TX> 00588 inline void for_all(TX & tx) 00589 { 00590 for_exec<EXEC, L>::all(tx); 00591 } 00592 00593 template <class T> 00594 struct has_depends_on : public sfinae_test<T, has_depends_on> 00595 { 00596 template <class U> has_depends_on(U*, typename U::depends_on* = 0); 00597 }; 00598 template <class T> 00599 struct has_implies : public sfinae_test<T, has_implies> 00600 { 00601 template <class U> has_implies(U*, typename U::implies_types* = 0); 00602 }; 00603 template <class T> 00604 struct has_follows : public sfinae_test<T, has_follows> 00605 { 00606 template <class U> has_follows(U*, typename U::follows_types* = 0); 00607 }; 00608 00609 // use empty list in case of lacking / faulty depends_on or implies_types: 00610 template <bool P, class T> 00611 struct depends_on_guard; 00612 template <class T> 00613 struct depends_on_guard<false, T> 00614 { 00615 typedef nil type; 00616 }; 00617 template <class T> 00618 struct depends_on_guard<true, T> 00619 { 00620 typedef typename list_guard<typename T::depends_on>::type type; 00621 }; 00622 template <class T> 00623 struct get_pure_depends_on 00624 { 00625 typedef typename depends_on_guard<has_depends_on<T>::value, T>::type 00626 type; 00627 }; 00628 00629 template <bool P, class T> 00630 struct follows_guard; 00631 template <class T> 00632 struct follows_guard<false, T> 00633 { 00634 typedef nil type; 00635 }; 00636 template <class T> 00637 struct follows_guard<true, T> 00638 { 00639 typedef typename list_guard<typename T::follows_types>::type type; 00640 }; 00641 template <class T> 00642 struct get_follows 00643 { 00644 typedef typename follows_guard<has_follows<T>::value, T>::type 00645 type; 00646 }; 00647 00648 template <class T> 00649 struct get_depends_on 00650 { 00651 typedef typename merge<typename get_pure_depends_on<T>::type, 00652 typename get_follows<T>::type >::type type; 00653 }; 00654 00655 template <bool P, class T> 00656 struct implies_guard; 00657 template <class T> 00658 struct implies_guard<false, T> 00659 { 00660 typedef nil type; 00661 }; 00662 template <class T> 00663 struct implies_guard<true, T> 00664 { 00665 typedef typename list_guard<typename T::implies_types>::type type; 00666 }; 00667 template <class T> 00668 struct get_implies 00669 { 00670 typedef typename implies_guard<has_implies<T>::value, T>::type 00671 type; 00672 }; 00673 00674 template <class L> struct implies_expand 00675 { 00676 typedef typename L::first first; 00677 typedef typename L::rest rest; 00678 typedef 00679 cons<first, typename 00680 merge<typename 00681 implies_expand<rest>::type, typename 00682 implies_expand<typename 00683 get_implies<first> 00684 ::type>::type>::type> type; 00685 }; 00686 template <> struct implies_expand<nil> 00687 { 00688 typedef nil type; 00689 }; 00690 00691 // for_all with type list == T::depends_on (if any.) 00692 template <class T, template<class> class EXEC, class TX> 00693 inline void for_all_used(TX & tx) 00694 { 00695 for_all<typename get_pure_depends_on<T>::type, EXEC>(tx); 00696 } 00697 00698 template <class X, class T> 00699 struct contains_dependent 00700 { 00701 static const bool value 00702 = contains<X, typename get_depends_on<T>::type>::value; 00703 }; 00704 00705 template <class X, class XL> struct is_independent_on 00706 { 00707 static const bool value 00708 = ChooseBool<contains_dependent<X, typename XL::first>, 00709 VigraFalseType, 00710 is_independent_on<X, typename XL::rest> 00711 >::value; 00712 }; 00713 template <class X> struct is_independent_on<X, nil> 00714 { 00715 static const bool value = true; 00716 }; 00717 00718 template <class XL, class YL = XL> struct get_independent 00719 { 00720 typedef typename YL::first YL_first; 00721 typedef typename 00722 IfBool<is_independent_on<YL_first, XL>::value, 00723 YL_first, 00724 typename get_independent<XL, typename YL::rest>::type 00725 >::type type; 00726 }; 00727 template <class XL> struct get_independent<XL, nil> 00728 { 00729 typedef nil type; 00730 }; 00731 00732 // the output is a list of types in reverse order, starting with the 00733 // most depedent types. 00734 template <class L> struct topo_sort 00735 { 00736 typedef typename get_independent<L>::type indep; 00737 typedef typename 00738 if_nil<indep, 00739 nil, 00740 cons<indep, 00741 typename topo_sort<typename remove<indep, L>::type>::type 00742 > 00743 >::type type; 00744 }; 00745 template <> struct topo_sort<nil> 00746 { 00747 typedef nil type; 00748 }; 00749 00750 // Topological sort -- the input is a list of types (see below), 00751 // each of which may, optionally, have an embedded typedef 'depends_on' 00752 // set to a singly-linked-list of types declared 00753 // using vigra::type_lists::cons, such as 00754 // cons<type_a, cons<type_b, cons<type_c> > > 00755 // (a one-parameter cons will add the trailing nil automatically), 00756 // -- the output is a list of types with increasing dependence, 00757 // starting with the indepedent types. 00758 // Types that should be said lists -- but are in fact not -- are silently 00759 // replaced by empty lists. 00760 00761 template <class L> struct topological_sort 00762 { 00763 typedef typename 00764 reverse<typename 00765 topo_sort<typename 00766 unique<typename 00767 list_guard<L> 00768 ::type>::type>::type>::type type; 00769 }; 00770 00771 template <class L> struct topological_sort_expanded 00772 { 00773 typedef typename 00774 topological_sort<typename 00775 implies_expand<L> 00776 ::type>::type type; 00777 }; 00778 00779 template <class V, unsigned pos = 0> 00780 class cond_val : public V 00781 { 00782 typedef V load_type; 00783 protected: 00784 bool is_set_; 00785 public: 00786 cond_val() : is_set_(false) {} 00787 const V & val() const { return *this; } 00788 V & val() { return *this; } 00789 00790 template <class TUPLE> 00791 bool is_set(const TUPLE &) const 00792 { 00793 return is_set_; 00794 } 00795 00796 template <class TUPLE> 00797 void set(TUPLE &) 00798 { 00799 is_set_ = true; 00800 } 00801 template <class TUPLE> 00802 void set(const V & v, TUPLE & tuple) 00803 { 00804 set(tuple); 00805 val() = v; 00806 } 00807 friend std::ostream & operator<<(std::ostream & os, const cond_val & x) 00808 { 00809 if (x.is_set_) 00810 os << x.val(x); 00811 else 00812 os << "<nil>"; 00813 return os; 00814 } 00815 }; 00816 00817 template <class V, unsigned pos> 00818 class bit_cond_val : public V 00819 { 00820 typedef V load_type; 00821 public: 00822 const V & val() const { return *this; } 00823 V & val() { return *this; } 00824 00825 template <class TUPLE> 00826 bool is_set(const TUPLE & tuple) const 00827 { 00828 return tuple.template is_bit_set<pos>(); 00829 } 00830 00831 template <class TUPLE> 00832 void set(TUPLE & tuple) 00833 { 00834 tuple.template set_bit<pos>(); 00835 } 00836 template <class TUPLE> 00837 void set(const V & v, TUPLE & tuple) 00838 { 00839 set(tuple); 00840 val() = v; 00841 } 00842 }; 00843 00844 // no templated virtual functions in C++ ... 00845 // 00846 // simple_member_dispatch: sample base and polymorphic adapter classes 00847 // for cond_virtual_tuple / etc. 00848 // -- the names 'member_base_type' and 'load_type' of the templates, 00849 // and also their parameter types, are fixed. 00850 // -- note that the member_base_type template of any "member_dispatch" 00851 // class can not directly serve as a base class for any member type that 00852 // is used within the tuple, since the signatures of most of the 00853 // virtual functions that are usually needed necessarily require the 00854 // type of the tuple itself. 00855 // 00856 struct simple_member_dispatch 00857 { 00858 template <class ACX, class T> 00859 struct member_base_type 00860 { 00861 virtual void operator()() {} 00862 virtual void operator()(ACX &, const T &) {} 00863 virtual void operator()(const ACX &, const ACX &, const ACX &) {} 00864 virtual void call(ACX &, const T &, unsigned) {} 00865 virtual ~member_base_type() {} 00866 }; 00867 template <class ACX, class T, class V> 00868 struct load_type : public member_base_type<ACX, T>, public V 00869 { 00870 load_type() {} 00871 load_type(const V & v) : V(v) {} 00872 void operator()() 00873 { 00874 V::operator()(); 00875 } 00876 void operator()(ACX & x, const T & v) 00877 { 00878 V::operator()(x, v); 00879 } 00880 void operator()(const ACX & z, const ACX & x, const ACX & y) 00881 { 00882 V::operator()(z, x, y); 00883 } 00884 void call(ACX & x, const T & v, unsigned n) 00885 { 00886 V::call(x, v, n); 00887 } 00888 }; 00889 }; 00890 00891 // polymorphic (conditional) tuple entry, modelled after cond_val 00892 template <class ACX, class T, class Z, class V> 00893 class tuple_entry 00894 { 00895 typedef typename Z::template load_type<ACX, T, V> load_type; 00896 typedef load_type* ptr_type; 00897 00898 protected: 00899 ptr_type p; 00900 00901 public: 00902 tuple_entry() : p(0) {} 00903 template <class TUPLE> 00904 bool is_set(const TUPLE &) const { return p != 0; } 00905 00906 protected: 00907 void make_load() 00908 { 00909 if (!p) 00910 p = new load_type; 00911 } 00912 void assign(const V & v) 00913 { 00914 ptr_type tmp = new load_type(v); 00915 delete p; 00916 p = tmp; 00917 } 00918 void check_pointer() const 00919 { 00920 if (!p) 00921 vigra_fail("tuple_entry::operator V &: unused tuple entry " 00922 "type V = [" + std::string(typeid(V).name()) + "], " 00923 "use set() to create an entry."); 00924 } 00925 public: 00926 operator const V & () const 00927 { 00928 check_pointer(); 00929 return *p; 00930 } 00931 operator V & () 00932 { 00933 check_pointer(); 00934 return *p; 00935 } 00936 00937 template <class TUPLE> // not neccearily identical to ACX 00938 void set(TUPLE & tuple) 00939 { 00940 make_load(); 00941 } 00942 template <class TUPLE> 00943 void set(const V & v, TUPLE & tuple) 00944 { 00945 set(tuple); 00946 assign(v); 00947 } 00948 00949 tuple_entry & operator=(tuple_entry const & e) 00950 { 00951 ptr_type tmp = new load_type(*e.p); 00952 delete p; 00953 p = tmp; 00954 return *this; 00955 } 00956 tuple_entry(tuple_entry const & e) 00957 : p(0) 00958 { 00959 if (e.p) // properly care for empty original 00960 p = new load_type(*e.p); 00961 } 00962 ~tuple_entry() 00963 { 00964 delete p; 00965 } 00966 friend std::ostream & operator<<(std::ostream & os, 00967 const tuple_entry & x) 00968 { 00969 if (x.p) 00970 os << x.val(x); 00971 else 00972 os << "<nil>"; 00973 return os; 00974 } 00975 }; 00976 00977 // pos is the position of type V in the type list of the tuple 00978 template <class ACX, class T, class Z, class V, unsigned pos> 00979 struct cond_tuple_entry : public tuple_entry<ACX, T, Z, V> 00980 { 00981 template <class TUPLE> // not quite identical to ACX 00982 void set(TUPLE & tuple) 00983 { 00984 this->make_load(); 00985 tuple.template add<V>(this->p, pos); 00986 } 00987 template <class TUPLE> 00988 void reassign(TUPLE & tuple) 00989 { 00990 if (this->p) 00991 tuple.reassign(this->p, pos); 00992 } 00993 template <class TUPLE> 00994 void set(const V & v, TUPLE & tuple) 00995 { 00996 set(tuple); 00997 this->assign(v); 00998 } 00999 }; 01000 01001 // helper classes for tuples 01002 01003 template <unsigned pos, class X> 01004 struct at_finder 01005 { 01006 typedef at_finder<pos - 1, typename X::rest_type> next_type; 01007 typedef typename next_type::type type; 01008 static 01009 type & at(X & x) 01010 { 01011 return next_type::at(x.rest); 01012 } 01013 }; 01014 template <class X> 01015 struct at_finder<0, X> 01016 { 01017 typedef typename X::first_type type; 01018 static 01019 type & at(X & x) { 01020 return x.first; 01021 } 01022 }; 01023 01024 template <class T, class X> 01025 struct sub_finder 01026 { 01027 typedef typename X::rest_type rest_type; 01028 typedef sub_finder<T, rest_type> 01029 next_type; 01030 typedef typename next_type::type type; 01031 static type & object(X & x) 01032 { 01033 return next_type::object(x.rest); 01034 } 01035 static const type & const_object(const X & x) 01036 { 01037 return next_type::const_object(x.rest); 01038 } 01039 }; 01040 template <class X> 01041 struct sub_finder<typename X::finder_type, X> 01042 { 01043 typedef X type; 01044 static type & object(X & x) 01045 { 01046 return x; 01047 } 01048 static const type & const_object(const X & x) 01049 { 01050 return x; 01051 } 01052 }; 01053 01054 template <class T, class X> 01055 struct ref_finder 01056 { 01057 typedef sub_finder<T, X> finder; 01058 typedef typename finder::type::first_type type; 01059 static 01060 type & ref(X & x) 01061 { 01062 return finder::object(x).first; 01063 } 01064 static 01065 const type & ref(const X & x) 01066 { 01067 return finder::const_object(x).first; 01068 } 01069 }; 01070 01071 struct binder_0 01072 { 01073 template <class F> 01074 void operator()(F & first) 01075 { 01076 first(); 01077 } 01078 template <class F> 01079 void call(F & first) 01080 { 01081 first.call(); 01082 } 01083 }; 01084 template <class A> 01085 struct binder_1 01086 { 01087 A v; 01088 binder_1(A v_) : v(v_) {} 01089 template <class F> 01090 void operator()(F & first) 01091 { 01092 first(v); 01093 } 01094 template <class F> 01095 void call(F & first) 01096 { 01097 first.call(v); 01098 } 01099 }; 01100 template <class A, class B> 01101 struct binder_2 01102 { 01103 A v; 01104 B w; 01105 binder_2(A v_, B w_) : v(v_), w(w_) {} 01106 template <class F> 01107 void operator()(F & first) 01108 { 01109 first(v, w); 01110 } 01111 template <class F> 01112 void call(F & first) 01113 { 01114 first.call(v, w); 01115 } 01116 }; 01117 template <class A, class B, class C> 01118 struct binder_3 01119 { 01120 A v; 01121 B w; 01122 C x; 01123 binder_3(A v_, B w_, C x_) : v(v_), w(w_), x(x_) {} 01124 template <class F> 01125 void operator()(F & first) 01126 { 01127 first(v, w, x); 01128 } 01129 template <class F> 01130 void call(F & first) 01131 { 01132 first.call(v, w, x); 01133 } 01134 }; 01135 01136 // mechanism for iterative application of operator() to a tuple 01137 template <template <class> class TEST> 01138 struct exec_op_plain 01139 { 01140 template <class TUPLE, class B, class TBASE> 01141 static void exec(TUPLE & tuple, B & binder, const TBASE & z) 01142 { 01143 binder(tuple.first); 01144 tuple.rest.exec_bound_op(binder, z); 01145 } 01146 template <class TUPLE, class B, class TBASE> 01147 static void call(TUPLE & tuple, B & binder, const TBASE & z) 01148 { 01149 typedef typename TUPLE::ref_finder_type ref_finder_type; 01150 if (TEST<ref_finder_type>::value) 01151 binder.call(static_cast<ref_finder_type &> (tuple.first)); 01152 tuple.rest.call_bound_op(binder, z); 01153 } 01154 }; 01155 01156 // policy classes for tuples 01157 struct plain_global_data 01158 { 01159 void reassign() {} 01160 }; 01161 01162 struct plain_chooser // this policy does effectively nothing. 01163 { 01164 template <class V, unsigned pos = 0> 01165 struct use 01166 { 01167 typedef V type; 01168 }; 01169 01170 template <class, template <class> class TEST> 01171 struct exec_op : public exec_op_plain<TEST> {}; 01172 01173 // "M" & "S" -> bug in cl.exe's parser. 01174 template <template<class, class, template<class> class M, unsigned> 01175 class, class, template<class> class S, unsigned> 01176 struct global_data : public plain_global_data 01177 { 01178 typedef global_data global_data_type; 01179 }; 01180 template <class QV, class TUPLE> 01181 static bool is_set(const QV &, const TUPLE &) { return true; } 01182 template <class QV, class TUPLE> 01183 static void set(QV &, TUPLE &) {} 01184 }; 01185 01186 // this policy uses the cond_val template to annotate 01187 // each tuple member with a bool that steers conditional 01188 // execution of each member's operator(), if called via 01189 // the tuple's operator(). 01190 struct cond_chooser_plain : public plain_chooser 01191 { 01192 template <class V, unsigned pos = 0> 01193 struct use 01194 { 01195 typedef cond_val<V, pos> type; 01196 }; 01197 01198 template <class, template <class> class TEST> 01199 struct exec_op 01200 { 01201 template <class TUPLE, class B, class TBASE> 01202 static void exec(TUPLE & tuple, B & binder, const TBASE & z) 01203 { 01204 typedef typename TUPLE::ref_finder_type ref_finder_type; 01205 if (tuple.first.is_set(z)) 01206 binder(static_cast<ref_finder_type &>(tuple.first)); 01207 tuple.rest.exec_bound_op(binder, z); 01208 } 01209 template <class TUPLE, class B, class TBASE> 01210 static void call(TUPLE & tuple, B & binder, const TBASE & z) 01211 { 01212 typedef typename TUPLE::ref_finder_type ref_finder_type; 01213 if (TEST<ref_finder_type>::value) 01214 if (tuple.first.is_set(z)) 01215 binder.call(static_cast<ref_finder_type &> 01216 (tuple.first)); 01217 tuple.rest.call_bound_op(binder, z); 01218 } 01219 }; 01220 01221 template <class QV, class TUPLE> 01222 static bool is_set(const QV & qv, const TUPLE & t) 01223 { 01224 return qv.is_set(t); 01225 } 01226 template <class QV, class TUPLE> 01227 static void set(QV & qv, TUPLE & t) 01228 { 01229 qv.set(t); 01230 } 01231 }; 01232 01233 // start the machinery for cond_chooser that produces nested 'if's 01234 01235 template <class X, class T, class L = typename get_pure_depends_on<T>::type> 01236 struct depends_on_deep 01237 { 01238 static const bool value = 01239 depends_on_deep<X, T, typename L::rest>::value // iterate list 01240 || depends_on_deep<X, typename L::first>::value; // indirect dep. 01241 }; 01242 template <class T, class L> 01243 struct depends_on_deep<typename L::first, T, L> 01244 { 01245 static const bool value = true; 01246 }; 01247 template <class X, class T> 01248 struct depends_on_deep<X, T, nil> 01249 { 01250 static const bool value = false; 01251 }; 01252 01253 template <class T, class R> 01254 struct first_depends_on 01255 { 01256 static const bool value 01257 = depends_on_deep<typename R::first, T>::value; 01258 }; 01259 template <class T> 01260 struct first_depends_on<T, nil> 01261 { 01262 static const bool value = false; 01263 }; 01264 01265 template <class RRL, class R> 01266 struct first_depends_on_all_of 01267 { 01268 static const bool value 01269 = ChooseBool< 01270 first_depends_on<typename 01271 RRL::first, 01272 R 01273 >, 01274 first_depends_on_all_of<typename RRL::rest, R>, 01275 VigraFalseType 01276 >::value; 01277 }; 01278 template <class R> // end of list RRL: 'success' 01279 struct first_depends_on_all_of<nil, R> 01280 { 01281 static const bool value = true; 01282 }; 01283 template <class RRL> // 'invalid' input (e.g., at end of cond_op recursion) 01284 struct first_depends_on_all_of<RRL, nil> 01285 { 01286 static const bool value = false; 01287 }; 01288 template <> // 'invalid' input (e.g., at end of cond_op recursion) 01289 struct first_depends_on_all_of<nil, nil> 01290 { 01291 static const bool value = false; 01292 }; 01293 01294 // helper structs for cond_op: 01295 struct null_exec 01296 { 01297 template <class TUPLE, class B, class TBASE> 01298 static void exec(TUPLE &, B &, const TBASE &) {} 01299 template <class TUPLE, class B, class TBASE> 01300 static void call(TUPLE &, B &, const TBASE &) {} 01301 typedef nil iter_leftover_type; 01302 }; 01303 template <bool cond, class EX> 01304 struct if_then 01305 { 01306 template <class TUPLE, class B, class TBASE> 01307 static void exec(TUPLE & t, B & b, const TBASE & z) 01308 { 01309 IfBool<cond, EX, null_exec>::type::exec(t, b, z); 01310 } 01311 template <class TUPLE, class B, class TBASE> 01312 static void call(TUPLE & t, B & b, const TBASE & z) 01313 { 01314 IfBool<cond, EX, null_exec>::type::call(t, b, z); 01315 } 01316 }; 01317 template <class ZL, template <class> class TEST, class RRL> 01318 struct cond_op_inner; 01319 01320 template <class ZL, template <class> class TEST, class RRL = nil> 01321 struct cond_op 01322 { 01323 typedef typename ZL::first first_type; 01324 typedef typename ZL::rest rest_type; 01325 typedef cons<first_type, RRL> next_rr_list; 01326 01327 static const bool recurse_deep 01328 = first_depends_on<first_type, rest_type>::value; 01329 typedef cond_op<rest_type, TEST, next_rr_list> 01330 deep_type; 01331 01332 typedef typename IfBool<recurse_deep, typename 01333 deep_type::iter_leftover_type, 01334 rest_type 01335 >::type 01336 deep_leftover_type; 01337 01338 static const bool iterate 01339 = first_depends_on_all_of<RRL, deep_leftover_type>::value; 01340 01341 typedef cond_op_inner<deep_leftover_type, TEST, RRL> 01342 iter_type; 01343 01344 // the type list left over from the deep first recursion of exec() 01345 // and the iteration step: the recursion patterns of both the type 01346 // 'iter_leftover_type' and the function 'exec()' must match. 01347 typedef typename IfBool<iterate, typename 01348 iter_type::iter_leftover_type, 01349 deep_leftover_type 01350 >::type 01351 iter_leftover_type; 01352 01353 // the code generation templates 01354 template <class TUPLE, class B, class TBASE> 01355 static void exec(TUPLE & tuple, B & binder, const TBASE & z) 01356 { 01357 if (tuple.first.is_set(z)) 01358 { 01359 binder(tuple.first); 01360 if_then<recurse_deep, deep_type>::exec(tuple.rest, binder, z); 01361 } 01362 if_then<iterate, iter_type>::exec(tuple, binder, z); 01363 } 01364 template <class TUPLE, class B, class TBASE> 01365 static void call(TUPLE & tuple, B & binder, const TBASE & z) 01366 { 01367 if (tuple.first.is_set(z)) 01368 { 01369 typedef typename TUPLE::ref_finder_type ref_finder_type; 01370 if (TEST<ref_finder_type>::value) 01371 binder.call(static_cast<ref_finder_type &> (tuple.first)); 01372 01373 if_then<recurse_deep, deep_type>::call(tuple.rest, binder, z); 01374 } 01375 if_then<iterate, iter_type>::call(tuple, binder, z); 01376 } 01377 }; 01378 template <template <class> class TEST, class RRL> // end of type list ZL 01379 struct cond_op<nil, TEST, RRL> : public null_exec {}; 01380 01381 template <template <class> class TEST, class RRL> // end of type list ZL 01382 struct cond_op_inner<nil, TEST, RRL> : public null_exec {}; 01383 01384 template <class ZL, template <class> class TEST, class RRL> 01385 struct cond_op_inner 01386 { 01387 typedef cond_op<ZL, TEST, RRL> exec_type; 01388 typedef typename exec_type::iter_leftover_type iter_leftover_type; 01389 01390 template <class TUPLE, class B, class TBASE> 01391 static void exec(TUPLE & tuple, B & binder, const TBASE & z) 01392 { 01393 exec_type:: 01394 exec(sub_finder<typename ZL::first, TUPLE>::object(tuple), 01395 binder, 01396 z); 01397 } 01398 template <class TUPLE, class B, class TBASE> 01399 static void call(TUPLE & tuple, B & binder, const TBASE & z) 01400 { 01401 exec_type:: 01402 call(sub_finder<typename ZL::first, TUPLE>::object(tuple), 01403 binder, 01404 z); 01405 } 01406 }; 01407 01408 struct cond_chooser : public cond_chooser_plain 01409 { 01410 template <class ZL, template <class> class TEST> 01411 struct exec_op : public cond_op<ZL, TEST> {}; 01412 }; 01413 01414 struct bit_cond_chooser : public cond_chooser 01415 { 01416 template <class V, unsigned pos> 01417 struct use 01418 { 01419 typedef bit_cond_val<V, pos> type; 01420 }; 01421 01422 // cl.exe wants this -- maybe it is right. 01423 template <template<class, class, template<class> class M, unsigned> 01424 class, class, template<class> class S, unsigned> 01425 struct global_data : public plain_global_data 01426 { 01427 typedef global_data global_data_type; 01428 }; 01429 template <template<class, class, template<class> class M, unsigned> 01430 class TBASE, class ITL, template<class> class TEST> 01431 struct global_data<TBASE, ITL, TEST, 0> : public plain_global_data 01432 { 01433 // typedef to catch our copy constructor and assignment operator: 01434 typedef global_data global_data_type; 01435 01436 BitArray<size<ITL>::of> bit_set; 01437 01438 void clear() { bit_set.clear(); } 01439 template <unsigned pos> 01440 void set_bit() { bit_set.template set<pos>(); } 01441 template <unsigned pos> 01442 bool is_bit_set() const { return bit_set.template test<pos>(); } 01443 }; 01444 }; 01445 01446 template <class ACX, class T, class Z> 01447 struct virtual_chooser: public cond_chooser_plain 01448 { 01449 template <class V, unsigned pos = 0> 01450 struct use 01451 { 01452 typedef tuple_entry<ACX, T, Z, V> type; 01453 }; 01454 }; 01455 01456 template <class T> struct set_exec 01457 { 01458 template <class ACX> 01459 static void exec(ACX & x) 01460 { 01461 x.template set<T>(); 01462 } 01463 }; 01464 01465 template <class ACX, class T, class Z> 01466 struct cond_virtual_chooser: public cond_chooser_plain 01467 { 01468 template <class V, unsigned pos = 0> 01469 struct use 01470 { 01471 typedef cond_tuple_entry<ACX, T, Z, V, pos> type; 01472 }; 01473 01474 template <class, template <class> class TEST> 01475 struct exec_op 01476 { 01477 template <class TUPLE, class B, class TBASE> 01478 static void exec(TUPLE & tuple, B & binder, const TBASE &) 01479 { 01480 for (unsigned i = 0; i != tuple.execs.size; ++i) 01481 binder(*tuple.execs.pointers[i]); 01482 } 01483 template <class TUPLE, class B, class TBASE> 01484 static void call(TUPLE & tuple, B & binder, const TBASE &) 01485 { 01486 for (unsigned i = 0; i != tuple.callers.size; ++i) 01487 binder.call(*tuple.callers.pointers[i]); 01488 } 01489 }; 01490 // cl.exe wants this -- maybe it is right. 01491 template <template<class, class, template<class> class M, unsigned> 01492 class, class, template<class> class S, unsigned> 01493 struct global_data : public plain_global_data 01494 { 01495 typedef global_data global_data_type; 01496 }; 01497 01498 template <class ITL> 01499 struct global_data_pointers // weak pointers 01500 { 01501 typedef typename Z::template member_base_type<ACX, T>* pointer_type; 01502 static const unsigned array_len = size<ITL>::of; 01503 01504 unsigned orders [array_len]; // consciously use two arrays 01505 unsigned size; 01506 pointer_type pointers[array_len]; 01507 01508 void clear() 01509 { 01510 size = 0; 01511 } 01512 global_data_pointers() 01513 { 01514 clear(); 01515 } 01516 unsigned* end(unsigned* = 0) 01517 { 01518 return orders + size; 01519 } 01520 pointer_type* end(pointer_type*) 01521 { 01522 return pointers + size; 01523 } 01524 template <class E> 01525 void make_room(E* i) 01526 { 01527 std::copy_backward(i, end(i), end(i) + 1); 01528 } 01529 typedef std::pair<unsigned*, pointer_type*> finder; 01530 bool find(unsigned pos, finder & found) 01531 { 01532 found.first = std::lower_bound(orders, end(), pos); 01533 found.second = pointers + (found.first - orders); 01534 return found.first != end() && *found.first == pos; 01535 } 01536 void add(pointer_type p, unsigned pos) 01537 { 01538 // merge pointer according to its topological sort order 01539 finder found; 01540 if (find(pos, found)) 01541 return; 01542 make_room(found.first); 01543 make_room(found.second); 01544 ++size; 01545 *found.first = pos; 01546 *found.second = p; 01547 } 01548 void reassign(pointer_type p, unsigned pos) 01549 { 01550 // replace pointers -- the present values still belong to 01551 // the old tuple object that was copied from 01552 finder found; 01553 if (find(pos, found)) 01554 *found.second = p; 01555 } 01556 }; 01557 template <template<class, class, template<class> class M, unsigned> 01558 class TBASE, class ITL, template<class> class TEST> 01559 struct global_data<TBASE, ITL, TEST, 0> 01560 { 01561 // typedef to catch our copy constructor and assignment operator: 01562 typedef global_data global_data_type; 01563 // the derived class: 01564 typedef TBASE<ITL, cond_virtual_chooser, TEST, 0> crtp_type; 01565 01566 typedef global_data_pointers<ITL> ptrs_type; 01567 typedef typename ptrs_type::pointer_type pointer_type; 01568 ptrs_type callers; 01569 ptrs_type execs; 01570 01571 template <class V> 01572 void add(pointer_type p, unsigned pos) 01573 { 01574 execs.add(p, pos); 01575 if (TEST<V>::value) 01576 callers.add(p, pos); 01577 } 01578 void reassign(pointer_type p, unsigned pos) 01579 { 01580 execs. reassign(p, pos); 01581 callers.reassign(p, pos); 01582 } 01583 01584 template <class V> 01585 struct reassign_op 01586 { 01587 static void exec(crtp_type & tuple) 01588 { 01589 tuple.template ref<V>().reassign(tuple); 01590 } 01591 }; 01592 01593 void reassign() 01594 { 01595 for_all<ITL, reassign_op>(static_cast<crtp_type &>(*this)); 01596 } 01597 }; 01598 }; 01599 01600 01601 template <class ITL, class Q = plain_chooser, 01602 template<class> class TEST = true_test, unsigned index = 0> 01603 struct tuple_base 01604 : public Q::template global_data<tuple_base, ITL, TEST, index> 01605 { 01606 typedef typename tuple_base::global_data_type global_data_base_type; 01607 typedef nil derived_type; // dummy declaration for static_cast_2<> 01608 typedef tuple_base tuple_type; 01609 typedef ITL list_type; 01610 01611 // use the original types from the list to find tuple members via ref(): 01612 typedef typename ITL::first finder_type; 01613 typedef typename ITL::rest rest_list_type; 01614 01615 typedef tuple_base<rest_list_type, Q, TEST, index + 1> rest_type; 01616 01617 // use policy class Q to annotate the types of the type list ITL 01618 // for use as members of the tuple: 01619 // -- the actually stored type 01620 typedef typename ITL::first ref_finder_type; 01621 typedef typename Q::template use<ref_finder_type, 01622 index>::type first_type; 01623 first_type first; 01624 rest_type rest; 01625 01626 template <class T> 01627 struct has_element 01628 { 01629 static const bool value = contains<T, ITL>::value; 01630 }; 01631 01632 template <unsigned pos> 01633 typename at_finder<pos, tuple_base>::type & at() 01634 { 01635 return at_finder<pos, tuple_base>::at(*this); 01636 } 01637 01638 template <class T> 01639 struct ref_returns 01640 { 01641 typedef ref_finder<T, tuple_base> finder; 01642 typedef typename finder::type ref_finder_type; 01643 typedef ref_finder_type & type; 01644 typedef const ref_finder_type & const_type; 01645 }; 01646 template <class T> 01647 typename ref_returns<T>::type 01648 ref() 01649 { 01650 return ref_returns<T>::finder::ref(*this); 01651 } 01652 template <class T> 01653 typename ref_returns<T>::const_type 01654 ref() const 01655 { 01656 return ref_returns<T>::finder::ref(*this); 01657 } 01658 01659 template <class V> 01660 bool is_set() const 01661 { 01662 return Q::template is_set(this->template ref<V>(), *this); 01663 } 01664 template <class RV> 01665 void set_if_not(RV & rv) 01666 { 01667 if (! Q::template is_set(rv, *this)) 01668 Q::template set(rv, *this); 01669 } 01670 // recursively set all the cond_val::is_set bits of the depended-on 01671 // types, or, respectively, take equivalent action. 01672 template <class V> 01673 void set() 01674 { 01675 set_if_not(this->template ref<V>()); 01676 for_all_used<V, set_exec>(*this); 01677 } 01678 // transfer the set bits of *this to another tuple t2: 01679 // (ITL must be a subset of ITL2.) 01680 template <class ITL2, class Q2, template<class> class TEST2> 01681 void transfer_set_to(tuple_base<ITL2, Q2, TEST2> & t2) const 01682 { 01683 if (is_set<ref_finder_type>()) 01684 t2.template set<ref_finder_type>(); 01685 rest.transfer_set_to(t2); 01686 } 01687 01688 // policy-based application of operator() 01689 template <class B, class TBASE> 01690 void exec_bound_op(B & binder, const TBASE & z) 01691 { 01692 Q::template exec_op<list_type, true_test>::exec(*this, binder, z); 01693 } 01694 template <class B> 01695 void exec_bound(B & binder) 01696 { 01697 exec_bound_op(binder, *this); 01698 } 01699 01700 void operator()() 01701 { 01702 binder_0 binder; 01703 exec_bound(binder); 01704 } 01705 01706 template <class A> 01707 void operator()(const A & v) 01708 { 01709 binder_1<const A &> binder(v); 01710 exec_bound(binder); 01711 } 01712 template <class A> 01713 void operator()(A & v) 01714 { 01715 binder_1<A &> binder(v); 01716 exec_bound(binder); 01717 } 01718 template <class A> 01719 void operator()(A & v) const 01720 { 01721 binder_1<A &> binder(v); 01722 exec_bound(binder); 01723 } 01724 01725 template <class A, class B> 01726 void operator()(const A & v, const B & w) 01727 { 01728 binder_2<const A &, const B &> binder(v, w); 01729 exec_bound(binder); 01730 } 01731 template <class A, class B> 01732 void operator()(A & v, const B & w) 01733 { 01734 binder_2<A &, const B &> binder(v, w); 01735 exec_bound(binder); 01736 } 01737 template <class A, class B> 01738 void operator()(A & v, const B & w) const 01739 { 01740 binder_2<A &, const B &> binder(v, w); 01741 exec_bound(binder); 01742 } 01743 01744 template <class A, class B, class C> 01745 void operator()(const A & v, const B & w, const C & x) 01746 { 01747 binder_3<const A &, const B &, const C &> binder(v, w, x); 01748 exec_bound(binder); 01749 } 01750 template <class A, class B, class C> 01751 void operator()(A & v, const B & w, const C & x) 01752 { 01753 binder_3<A &, const B &, const C &> binder(v, w, x); 01754 exec_bound(binder); 01755 } 01756 template <class A, class B, class C> 01757 void operator()(A & v, const B & w, const C & x) const 01758 { 01759 binder_3<A &, const B &, const C &> binder(v, w, x); 01760 exec_bound(binder); 01761 } 01762 01763 // policy-based application of call() 01764 template <class B, class TBASE> 01765 void call_bound_op(B & binder, const TBASE & z) 01766 { 01767 Q::template exec_op<list_type, TEST>::call(*this, binder, z); 01768 } 01769 template <class B> 01770 void call_bound(B & binder) 01771 { 01772 call_bound_op(binder, *this); 01773 } 01774 01775 template <class A, class B> 01776 void call(const A & v, const B & w) 01777 { 01778 binder_2<const A &, const B &> binder(v, w); 01779 call_bound(binder); 01780 } 01781 template <class A, class B> 01782 void call(A & v, const B & w) 01783 { 01784 binder_2<A &, const B &> binder(v, w); 01785 call_bound(binder); 01786 } 01787 template <class A, class B> 01788 void call(A & v, const B & w) const 01789 { 01790 binder_2<A &, const B &> binder(v, w); 01791 call_bound(binder); 01792 } 01793 01794 template <class A, class B, class C> 01795 void call(const A & v, const B & w, const C & x) 01796 { 01797 binder_3<const A &, const B &, const C &> binder(v, w, x); 01798 call_bound(binder); 01799 } 01800 template <class A, class B, class C> 01801 void call(A & v, const B & w, const C & x) 01802 { 01803 binder_3<A &, const B &, const C &> binder(v, w, x); 01804 call_bound(binder); 01805 } 01806 template <class A, class B, class C> 01807 void call(A & v, const B & w, const C & x) const 01808 { 01809 binder_3<A &, const B &, const C &> binder(v, w, x); 01810 call_bound(binder); 01811 } 01812 01813 // the possible reassign() of global data requires handmade copies here 01814 tuple_base() {} 01815 tuple_base(const tuple_base & x) 01816 : global_data_base_type(x), first(x.first), rest(x.rest) 01817 { 01818 this->reassign(); 01819 } 01820 tuple_base & operator=(const tuple_base & x) 01821 { 01822 global_data_base_type::operator=(x); 01823 first = x.first; 01824 rest = x.rest; 01825 this->reassign(); 01826 return *this; 01827 } 01828 }; 01829 template <class Q, template <class> class TEST, unsigned index> 01830 struct tuple_base<nil, Q, TEST, index> 01831 { 01832 template <class> 01833 struct has_element 01834 { 01835 static const bool value = false; 01836 }; 01837 template <class B, class TBASE> 01838 void exec_bound_op(B &, const TBASE &) {} 01839 template <class B, class TBASE> 01840 void call_bound_op(B &, const TBASE &) {} 01841 template <class ITL2, class Q2, template<class> class TEST2> 01842 void transfer_set_to(tuple_base<ITL2, Q2, TEST2> &) const {} 01843 }; 01844 01845 template <class V, class L, class A, class B> 01846 struct choose_tuple 01847 { 01848 static const bool value = contains<V, L>::value; 01849 typedef typename IfBool<value, A, B>::type type; 01850 static type & at(A & a, B & b) 01851 { 01852 return choose_type<value>::at(a, b); 01853 } 01854 static const type & at(const A & a, const B & b) 01855 { 01856 return choose_type<value>::at(a, b); 01857 } 01858 01859 typedef typename type::template ref_returns<V>:: type 01860 ref_type; 01861 typedef typename type::template ref_returns<V>::const_type 01862 const_ref_type; 01863 01864 ref_type 01865 static ref(A & a, B & b) 01866 { 01867 return at(a, b).template ref<V>(); 01868 } 01869 const_ref_type 01870 static ref(const A & a, const B & b) 01871 { 01872 return at(a, b).template ref<V>(); 01873 } 01874 }; 01875 01876 template <class ITL, template<class> class TEST = true_test> 01877 struct tuple : public tuple_base<ITL, plain_chooser, TEST> {}; 01878 01879 template <class ITL, template<class> class TEST = true_test> 01880 struct cond_tuple_plain 01881 : public tuple_base<ITL, cond_chooser_plain, TEST> {}; 01882 01883 template <class ITL, template<class> class TEST = true_test> 01884 struct cond_tuple : public tuple_base<ITL, cond_chooser, TEST> {}; 01885 01886 template <class ITL, template<class> class TEST = true_test> 01887 struct bit_cond_tuple : public tuple_base<ITL, bit_cond_chooser, TEST> {}; 01888 01889 template <class ITL, class ACX, class T, class Z, 01890 template<class> class TEST = true_test> 01891 struct virtual_tuple_base 01892 : public tuple_base<ITL, virtual_chooser<ACX, T, Z>, TEST> {}; 01893 01894 template <template <class, class> class ACXTT, class T, 01895 class Z = simple_member_dispatch> 01896 struct virtual_tuple 01897 { 01898 template <class ITL, template<class> class TEST = true_test> 01899 struct type 01900 : public virtual_tuple_base<ITL, ACXTT<T, ITL>, T, Z, TEST> {}; 01901 }; 01902 01903 template <class ITL, class ACX, class T, class Z, 01904 template<class> class TEST = true_test> 01905 struct cond_virtual_tuple_base 01906 : public tuple_base<ITL, cond_virtual_chooser<ACX, T, Z>, TEST> 01907 { 01908 typedef ACX derived_type; 01909 }; 01910 01911 template <template <class, class> class ACXTT, class T, 01912 class Z = simple_member_dispatch> 01913 struct cond_virtual_tuple 01914 { 01915 template <class ITL, template<class> class TEST = true_test> 01916 struct type 01917 : public cond_virtual_tuple_base<ITL, ACXTT<T, ITL>, T, Z, TEST> {}; 01918 }; 01919 01920 } // namespace type_lists 01921 01922 // mask cl.exe shortcomings [end] 01923 #if defined(_MSC_VER) 01924 #pragma warning( pop ) 01925 #endif 01926 01927 } // namespace vigra 01928 01929 #endif // VIGRA_TYPE_LISTS_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|