Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/meta.h

Go to the documentation of this file.
00001 
00002 //  Copyright (C) 1999--2002  Petter Urkedal
00003 
00004 //  This file is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (at your option) any later version.
00008 
00009 //  This file is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 //  As a special exception, you may use this file as part of a free
00019 //  software library without restriction.  Specifically, if other files
00020 //  instantiate templates or use macros or inline functions from this
00021 //  file, or you compile this file and link it with other files to
00022 //  produce an executable, this file does not by itself cause the
00023 //  resulting executable to be covered by the GNU General Public
00024 //  License.  This exception does not however invalidate any other
00025 //  reasons why the executable file might be covered by the GNU General
00026 //  Public License.
00027 
00028 //  $Id: meta.h,v 1.2 2002/08/24 14:02:45 petter_urkedal Exp $
00029 
00030 
00031 
00032 #ifndef MORE_GEN_META_H
00033 #define MORE_GEN_META_H
00034 
00035 namespace more {
00036 
00037 
00038 struct nulltype {
00039     typedef nulltype first_type;
00040     typedef nulltype second_type;
00041     operator bool() { return false; }
00042     operator int() { return 0; }
00043 };
00044 struct truetype {
00045     operator bool() { return true; }
00046     operator int() { return 1; }
00047 };
00048 
00049 template <class T, class U>
00050   struct typepair {
00051       typedef T first_type;
00052       typedef U second_type;
00053   };
00054 
00055 template<typename T> struct typepair_traits {
00056     static const int atomic = 1;
00057     static const int linear = 0;
00058     static const int arity = 0;
00059 };
00060 template<> struct typepair_traits<nulltype> {
00061     static const int atomic = 1;
00062     static const int linear = 1;
00063     static const int arity = 0;
00064 };
00065 
00066 template<typename T, typename U>
00067   struct typepair_traits< typepair<T, U> > {
00068       static const int atomic = 0;
00069       static const int linear =
00070         typepair_traits<T>::atomic && typepair_traits<U>::linear;
00071       static const int arity =
00072         typepair_traits<U>::arity + 1;
00073   };
00074 
00075 
00076 //  --- Logical operations ---
00077 //
00078 //  Please note the difference between equals_ and equiv_.  The last
00079 //  evaluates to truetype if either non or both arguments are nulltype;
00080 //  otherwise it returns nulltype.  equals_ compares the argument
00081 //  for exact equality.
00082 
00083 template <class Cond, class Positive, class Negative = nulltype>
00084 struct if_ { typedef Positive eval; };
00085 
00086 template <class Positive, class Negative>
00087 struct if_<nulltype, Positive, Negative> { typedef Negative eval; };
00088 
00089 template <class T> struct not_ { typedef nulltype eval; };
00090 template <> struct not_<nulltype> { typedef truetype eval; };
00091 
00092 template <class T, class U>  struct equals_ { typedef nulltype eval; };
00093 template <class T>           struct equals_<T, T> { typedef T eval; };
00094 template <> struct equals_<nulltype, nulltype> { typedef truetype eval; };
00095 
00096 template <class T, class U>  struct equiv_ { typedef truetype eval; };
00097 template <class T>    struct equiv_<T, nulltype> { typedef nulltype eval; };
00098 template <class U>    struct equiv_<nulltype, U> { typedef nulltype eval; };
00099 template <> struct equiv_<nulltype, nulltype> { typedef truetype eval; };
00100 
00101 template <class T1 = nulltype, class T2 = nulltype, class T3 = nulltype,
00102           class T4 = nulltype, class T5 = nulltype, class T6 = nulltype>
00103 struct or_ { typedef T1 eval; };
00104 template <class T2, class T3, class T4, class T5, class T6>
00105 struct or_<nulltype, T2, T3, T4, T5, T6> { typedef T2 eval; };
00106 template <class T3, class T4, class T5, class T6>
00107 struct or_<nulltype, nulltype, T3, T4, T5, T6> { typedef T3 eval; };
00108 template <class T4, class T5, class T6>
00109 struct or_<nulltype, nulltype, nulltype, T4, T5, T6> { typedef T4 eval; };
00110 template <class T5, class T6>
00111 struct or_<nulltype, nulltype, nulltype, nulltype, T5, T6>
00112     { typedef T5 eval; };
00113 template <class T6>
00114 struct or_<nulltype, nulltype, nulltype, nulltype, nulltype, T6>
00115     { typedef T6 eval; };
00116 
00117 #if 0
00118 template <class T1 = truetype, class T2 = T1, class T3 = T2,
00119           class T4 = T3,       class T5 = T4, class T6 = T5>
00120 struct and_ { typedef T6 eval; };
00121 template <class T2, class T3, class T4, class T5, class T6>
00122 struct and_<nulltype, T2, T3, T4, T5, T6> { typedef nulltype eval; };
00123 template <class T1, class T3, class T4, class T5, class T6>
00124 struct and_<T1, nulltype, T3, T4, T5, T6> { typedef nulltype eval; };
00125 template <class T1, class T2, class T4, class T5, class T6>
00126 struct and_<T1, T2, nulltype, T4, T5, T6> { typedef nulltype eval; };
00127 template <class T1, class T2, class T3, class T5, class T6>
00128 struct and_<T1, T2, T3, nulltype, T5, T6> { typedef nulltype eval; };
00129 template <class T1, class T2, class T3, class T4, class T6>
00130 struct and_<T1, T2, T3, T4, nulltype, T6> { typedef nulltype eval; };
00131 template <class T1, class T2, class T3, class T4, class T5>
00132 struct and_<T1, T2, T3, T4, T5, nulltype> { typedef nulltype eval; };
00133 #else
00134 template <class T1 = truetype, class T2 = T1, class T3 = T2,
00135           class T4 = T3,       class T5 = T4, class T6 = T5>
00136 struct and_ : public and_<T2, T3, T4, T5, T6, truetype> {};
00137 template <class T2, class T3, class T4, class T5, class T6>
00138 struct and_<nulltype, T2, T3, T4, T5, T6> { typedef nulltype eval; };
00139 template <class T>
00140 struct and_<T, truetype, truetype, truetype, truetype, truetype>
00141     { typedef T eval; };
00142 #endif
00143 
00144 template <class T, class U>  struct xor_ { typedef nulltype eval; };
00145 template <class T>           struct xor_<T, nulltype> { typedef T eval; };
00146 template <class U>           struct xor_<nulltype, U> { typedef U eval; };
00147 
00148 
00149 
00150 //  --- append_ ---
00151 //
00152 //  Appends an element to a type-list.
00153 //
00154 template <class List, class Value>
00155 struct append_ { typedef typename List::is_not_a_list eval; };
00156 
00157 template <class V>
00158 struct append_<nulltype, V> { typedef typepair<V, nulltype> eval; };
00159 
00160 template <class E, class Tail, class V>
00161 struct append_<typepair<E, Tail>, V>
00162 { typedef typepair<E, typename append_<Tail, V>::eval> eval; };
00163 
00164 
00165 //  --- concat_ ---
00166 //
00167 //  Concatinates two lists.
00168 
00169 template <class List, class List1>
00170 struct concat_ { typedef typename List::is_not_a_list eval; };
00171 
00172 template <class List1>
00173 struct concat_<nulltype, List1> { typedef List1 eval; };
00174 
00175 template <class E, class Tail, class List1>
00176 struct concat_<typepair<E, Tail>, List1>
00177 { typedef typepair<E, typename concat_<Tail, List1>::eval> eval; };
00178 
00179 
00180 //  --- tree_to_list ---
00181 //
00182 //  Expands a tree into a list
00183 
00184 template <class List>
00185 struct tree_to_list_ { typedef typepair<List, nulltype> eval; };
00186 
00187 template <class List, class List1>
00188 struct tree_to_list_< typepair<List, List1> > {
00189     typedef typename concat_
00190         < typename tree_to_list_<List>::eval,
00191           typename tree_to_list_<List1>::eval
00192         >::eval eval;
00193 };
00194 
00195 
00196 //  --- is_in_ ---
00197 
00198 template <class T, class List>
00199 struct is_in_ { typedef typename List::is_not_a_list eval; };
00200 
00201 template <class T, class U, class Tail>
00202 struct is_in_< T, typepair<U, Tail> >
00203 { typedef typename is_in_<T, Tail>::eval eval; };
00204 
00205 template <class T, class Tail>
00206 struct is_in_< T, typepair<T, Tail> > { typedef truetype eval; };
00207 
00208 template <class T>
00209 struct is_in_<T, nulltype> { typedef nulltype eval; };
00210 
00211 
00212 
00213 //  --- typeassert_ ---
00214 //
00215 //  Produces a compile-time error if its argument evaluates to nulltype
00216 //  The argument should not be evaluated in advance, since we want the
00217 //  compiler to print out the type-expression, if possible.
00218 
00219 
00220 template <class T>
00221 struct typeassert_ {
00222     typedef typename if_
00223       < typename not_< typename T::eval >::eval,
00224         typename T::ASSERTION_FAILED,
00225         T >::eval eval;
00226 };
00227 
00228 
00229 
00230 //  --- LIST ---
00231 //
00232 //  Defines a convenient type-function for producing lists with up to
00233 //  eight elements.
00234 
00235 template <class T1 = nulltype, class T2 = nulltype, class T3 = nulltype,
00236           class T4 = nulltype, class T5 = nulltype, class T6 = nulltype,
00237           class T7 = nulltype, class T8 = nulltype, class T9 = nulltype,
00238           class T10= nulltype, class T11= nulltype, class T12= nulltype>
00239 struct list_ {
00240     typedef typepair
00241         < T1, typepair< T2, typepair< T3, typepair
00242         < T4, typepair< T5, typepair< T6, typepair
00243         < T7, typepair< T8, typepair< T9, typepair
00244         <T10, typepair<T11, typepair<T12, nulltype > > > > > > > > > > > >
00245         eval;
00246 };
00247 
00248 template <class T1, class T2, class T3, class T4, class T5, class T6,
00249           class T7, class T8, class T9, class T10, class T11>
00250 struct list_<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> {
00251     typedef typepair
00252         < T1, typepair< T2, typepair< T3, typepair
00253         < T4, typepair< T5, typepair< T6, typepair
00254         < T7, typepair< T8, typepair< T9, typepair
00255         <T10, typepair<T11, nulltype > > > > > > > > > > >
00256         eval;
00257 };
00258 
00259 template <class T1, class T2, class T3, class T4, class T5, class T6,
00260           class T7, class T8, class T9, class T10>
00261 struct list_<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> {
00262     typedef typepair
00263         < T1, typepair< T2, typepair< T3, typepair
00264         < T4, typepair< T5, typepair< T6, typepair
00265         < T7, typepair< T8, typepair< T9, typepair
00266         <T10, nulltype > > > > > > > > > >
00267         eval;
00268 };
00269 
00270 template <class T1, class T2, class T3, class T4, class T5, class T6,
00271           class T7, class T8, class T9>
00272 struct list_<T1, T2, T3, T4, T5, T6, T7, T8, T9> {
00273     typedef typepair
00274         < T1, typepair< T2, typepair< T3, typepair
00275         < T4, typepair< T5, typepair< T6, typepair
00276         < T7, typepair< T8, typepair< T9, nulltype > > > > > > > > >
00277         eval;
00278 };
00279 
00280 template <class T1, class T2, class T3, class T4, class T5, class T6,
00281           class T7, class T8>
00282 struct list_<T1, T2, T3, T4, T5, T6, T7, T8> {
00283     typedef typepair
00284         < T1, typepair< T2, typepair< T3, typepair
00285         < T4, typepair< T5, typepair< T6, typepair
00286         < T7, typepair< T8, nulltype > > > > > > > >
00287         eval;
00288 };
00289 
00290 template <class T1, class T2, class T3, class T4, class T5, class T6,
00291           class T7>
00292 struct list_<T1, T2, T3, T4, T5, T6, T7> {
00293     typedef typepair
00294         < T1, typepair< T2, typepair< T3, typepair
00295         < T4, typepair< T5, typepair< T6, typepair
00296         < T7, nulltype > > > > > > >
00297         eval;
00298 };
00299 
00300 template <class T1, class T2, class T3, class T4, class T5, class T6>
00301 struct list_<T1, T2, T3, T4, T5, T6> {
00302     typedef typepair
00303         < T1, typepair< T2, typepair< T3, typepair
00304         < T4, typepair< T5, typepair< T6, nulltype > > > > > > eval;
00305 };
00306 
00307 template <class T1, class T2, class T3, class T4, class T5>
00308 struct list_<T1, T2, T3, T4, T5> {
00309     typedef typepair
00310         < T1, typepair< T2, typepair< T3, typepair
00311         < T4, typepair< T5, nulltype > > > > > eval;
00312 };
00313 
00314 template <class T1, class T2, class T3, class T4>
00315 struct list_<T1, T2, T3, T4> {
00316     typedef typepair
00317         < T1, typepair< T2, typepair< T3, typepair< T4, nulltype > > > >
00318         eval;
00319 };
00320 
00321 template <class T1, class T2, class T3> struct list_<T1, T2, T3>
00322 { typedef typepair< T1, typepair< T2, typepair< T3, nulltype > > > eval; };
00323 
00324 template <class T1, class T2> struct list_<T1, T2>
00325 { typedef typepair< T1, typepair< T2, nulltype > > eval; };
00326 
00327 template <class T1> struct list_<T1>
00328 { typedef typepair< T1, nulltype > eval; };
00329 
00330 template <> struct list_<> { typedef nulltype eval; };
00331 
00332 
00333 
00334 //  --- order_ ---
00335 
00336 template <class T1, class T2, class Ordering>
00337   class order_ { typedef typename Ordering::is_not_a_list eval; };
00338 template <class T1, class T2, class T3, class Tail>
00339   struct order_< T1, T2, typepair<T3, Tail> >
00340     { typedef typename order_<T1, T2, Tail>::eval eval; };
00341 template <class T1, class T2, class Tail>
00342   struct order_< T1, T2, typepair<T1, Tail> >
00343     { typedef typepair<T1, T2> eval; };
00344 template <class T1, class T2, class Tail>
00345   struct order_< T1, T2, typepair<T2, Tail> >
00346     { typedef typepair<T2, T1> eval; };
00347 template <class T, class Tail>
00348   struct order_< T, T, typepair<T, Tail> >
00349     { typedef typepair<T, T> eval; };
00350 template <class T1, class T2>
00351   struct order_< T1, T2, nulltype >
00352     { typedef nulltype eval; };
00353 
00354 
00355 
00356 //  --- Balanced types for (+, -, *, /, %) ---
00357 
00358 #if 0
00359 typedef list_< char, short, int, long, float, double, long double >::eval
00360     balanced_type_order;
00361 
00362 template <class T1, class T2>
00363 class commutative_balanced_type_ { typedef nulltype eval; };
00364 
00365 template <class T1, class T2>
00366 class balanced_type_ {
00367     typedef typename order_<T1, T2, balanced_type_order>::eval order;
00368 public:
00369     typedef typename or_
00370       < typename commutative_balanced_type_<T1, T2>::eval,
00371         typename commutative_balanced_type_<T2, T1>::eval,
00372         typename order::second_type,
00373         typename if_
00374           < typename is_in_<T1, balanced_type_order>::eval, T2
00375           > ::eval,
00376         typename if_
00377           < typename is_in_<T2, balanced_type_order>::eval, T1
00378           > ::eval
00379       > ::eval eval;
00380 };
00381 
00382 template <class T1, class T2>
00383 struct commutative_plus_type_ { typedef nulltype eval; };
00384 
00385 template <class T1, class T2>
00386 struct plus_type_ {
00387     typedef typename or_
00388       < typename commutative_plus_type_<T1, T2>::eval,
00389         typename commutative_plus_type_<T2, T1>::eval,
00390         typename balanced_type_<T1, T2>::eval >::eval eval;
00391 };
00392 
00393 template <class T1, class T2>
00394 struct commutative_minus_type_ { typedef nulltype eval; };
00395 
00396 template <class T1, class T2>
00397 struct minus_type_ {
00398     typedef typename or_
00399       < typename commutative_minus_type_<T1, T2>::eval,
00400         typename commutative_minus_type_<T2, T1>::eval,
00401         typename balanced_type_<T1, T2>::eval >::eval eval;
00402 };
00403 
00404 template <class T1, class T2>
00405 struct commutative_times_type_ { typedef nulltype eval; };
00406 
00407 template <class T1, class T2>
00408 struct times_type_ {
00409     typedef typename or_
00410       < typename commutative_times_type_<T1, T2>::eval,
00411         typename commutative_times_type_<T2, T1>::eval,
00412         typename balanced_type_<T1, T2>::eval >::eval eval;
00413 };
00414 
00415 template <class T1, class T2>
00416 struct commutative_divides_type_ { typedef nulltype eval; };
00417 
00418 template <class T1, class T2>
00419 struct divides_type_ {
00420     typedef typename or_
00421       < typename commutative_divides_type_<T1, T2>::eval,
00422         typename commutative_divides_type_<T2, T1>::eval,
00423         typename balanced_type_<T1, T2>::eval >::eval eval;
00424 };
00425 
00426 template <class T1, class T2>
00427 struct commutative_remainder_type_ { typedef nulltype eval; };
00428 
00429 template <class T1, class T2>
00430 struct remainder_type_ {
00431     typedef typename or_
00432       < typename commutative_remainder_type_<T1, T2>::eval,
00433         typename commutative_remainder_type_<T2, T1>::eval,
00434         typename balanced_type_<T1, T2>::eval >::eval eval;
00435 };
00436 #endif
00437 
00438 
00439 //  --- Definition of is_a_<T, U> ---
00440 
00441 template<typename T> inline char _meta_is_a_1(const void*, const T*) {}
00442 template<typename T> inline long _meta_is_a_1(const T*, const T*) {}
00443 
00444 template <int N> struct _longsize {};
00445 template <> struct _longsize<sizeof(char)> { typedef nulltype eval; };
00446 template <> struct _longsize<sizeof(long)> { typedef truetype eval; };
00447 
00448 #if 0
00449 template <class T, class U> class is_a_ {
00450 private:
00451     enum { size = sizeof(_meta_is_a_1(static_cast<T*>(0),
00452                                       static_cast<U*>(0))) };
00453 public:
00454     typedef typename _longsize<size>::eval eval;
00455 };
00456 #endif
00457 
00458 
00459 //  --- is_pointer_<T> ---
00460 
00461 template <class T> struct is_pointer_ { typedef nulltype eval; };
00462 template <class T> struct is_pointer_<T*> { typedef truetype eval; };
00463 
00464 
00465 //  --- is_class_<T> ---
00466 
00467 template <class T> struct is_class_ { typedef truetype eval; };
00468 template <class T> struct is_class_<T*> { typedef nulltype eval; };
00469 template <> struct is_class_<bool> { typedef nulltype eval; };
00470 template <> struct is_class_<char> { typedef nulltype eval; };
00471 template <> struct is_class_<signed char> { typedef nulltype eval; };
00472 template <> struct is_class_<unsigned char> { typedef nulltype eval; };
00473 template <> struct is_class_<short> { typedef nulltype eval; };
00474 template <> struct is_class_<unsigned short> { typedef nulltype eval; };
00475 template <> struct is_class_<int> { typedef nulltype eval; };
00476 template <> struct is_class_<unsigned int> { typedef nulltype eval; };
00477 template <> struct is_class_<long> { typedef nulltype eval; };
00478 template <> struct is_class_<unsigned long> { typedef nulltype eval; };
00479 template <> struct is_class_<float> { typedef nulltype eval; };
00480 template <> struct is_class_<double> { typedef nulltype eval; };
00481 template <> struct is_class_<long double> { typedef nulltype eval; };
00482 
00483 template <class T> struct is_etype_
00484 { typedef typename not_<typename is_class_<T>::eval>::eval eval; };
00485 
00486 
00487 //  --- is_true_ ---
00488 
00489 template <bool Cond> struct is_true_ { typedef nulltype eval; };
00490 template <> struct is_true_<true> { typedef truetype eval; };
00491 
00492 
00493 //  --- is_const_ ---
00494 
00495 template<typename T> struct is_const_ { typedef nulltype eval; };
00496 template<typename T> struct is_const_<const T> { typedef truetype eval; };
00497 
00498 //  --- bigger_type_ ---
00499 
00500 template <class T, class U> struct bigger_type_ {
00501     typedef typename if_
00502       < typename is_true_< (sizeof(T) >= sizeof(U)) >::eval,
00503         T, U >::eval eval;
00504 };
00505 
00506 //  --- to_unsigned_ ---
00507 
00508 template<typename T> struct to_unsigned_ { typedef T eval; };
00509 template<> struct to_unsigned_<char> { typedef unsigned char eval; };
00510 template<> struct to_unsigned_<signed char> { typedef unsigned char eval; };
00511 template<> struct to_unsigned_<short> { typedef unsigned short eval; };
00512 template<> struct to_unsigned_<int> { typedef unsigned int eval; };
00513 template<> struct to_unsigned_<long> { typedef unsigned long eval; };
00514 #ifdef MORE_HAVE_LONG_LONG
00515 template<> struct to_unsigned_<long long> { typedef unsigned long long eval; };
00516 #endif
00517 
00518 //  --- to_signed_ ---
00519 
00520 template<typename T> struct to_signed_ { typedef T eval; };
00521 template<> struct to_signed_<char> { typedef signed char eval; };
00522 template<> struct to_signed_<unsigned char> { typedef signed char eval; };
00523 template<> struct to_signed_<unsigned short> { typedef short eval; };
00524 template<> struct to_signed_<unsigned int> { typedef int eval; };
00525 template<> struct to_signed_<unsigned long> { typedef long eval; };
00526 #ifdef MORE_HAVE_LONG_LONG
00527 template<> struct to_signed_<unsigned long long> { typedef long long eval; };
00528 #endif
00529 
00530 
00531 } // more
00532 
00533 #endif

Generated on Sat Sep 7 19:11:19 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.