00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #ifdef _MSC_VER
00031 # pragma once
00032 # pragma warning( push )
00033 # pragma warning( disable : 4512 4786 )
00034 #endif // _MSC_VER
00035
00036 #ifndef _EXMAT_METAPROGRAMMING_H
00037 #define _EXMAT_METAPROGRAMMING_H
00038
00039 #include "PlatformSpec.h"
00040 #include "StaticAssert.h"
00041 #include "loki/TypeManip.h"
00042
00043 namespace exmat {
00044
00046
00050 template<int v> struct Int2Type
00051 { enum{ RET = v }; };
00052
00054
00057 template<class T> struct Type2Type
00058 { typedef T RET; };
00059
00060
00062
00067 template<bool B>
00068 struct EnableIf_c {
00069 typedef void RET;
00070 };
00071 template<>
00072 struct EnableIf_c<true> {
00073 typedef void RET;
00074 };
00075 template<>
00076 struct EnableIf_c<false> {
00077 };
00078 template<bool B>
00079 struct DisableIf_c {
00080 typedef void RET;
00081 };
00082 template<>
00083 struct DisableIf_c<true> {};
00085
00086
00088
00092 template<class Derived, class Base>
00093 class IsDerivedFrom {
00094 struct No {};
00095 struct Yes { No n_[3]; };
00096 struct Helper {
00097 static Yes Test(Base*);
00098 static No Test(...);
00099 };
00100 public:
00101 enum {
00102 RET = sizeof(Yes) ==
00103 sizeof( Helper::Test(static_cast<Derived*>(0)))
00104 };
00105 };
00106
00107
00109
00112 template<typename T1, typename T2>
00113 struct ISSAMETYPE {
00114 enum {
00115 #ifdef EXMAT_VC6
00116 RET = Loki::IsEqualType<T1, T2>::value
00117 #else
00118 RET = Loki::IsSameType<T1, T2>::value
00119 #endif
00120 };
00121 };
00122
00123
00125
00126 template<int Val1, int Val2>
00127 struct EQUAL {
00128 enum { RET = (Val1 == Val2) };
00129 };
00131 template<int Val1, int Val2>
00132 struct NOT_EQUAL {
00133 enum { RET = (Val1 != Val2) };
00134 };
00136 template<int Val1, int Val2>
00137 struct GREATER {
00138 enum { RET = (Val1 > Val2) };
00139 };
00141 template<int Val1, int Val2>
00142 struct GREATER_EQUAL {
00143 enum { RET = (Val1 >= Val2) };
00144 };
00146 template<int Val1, int Val2>
00147 struct LESS {
00148 enum { RET = (Val1 < Val2) };
00149 };
00151 template<int Val1, int Val2>
00152 struct LESS_EQUAL {
00153 enum { RET = (Val1 <= Val2) };
00154 };
00156
00157
00158
00160
00161 template<bool Val1, bool Val2>
00162 struct AND_bool {
00163 enum { RET = (Val1 && Val2) };
00164 };
00166 template<bool Val1, bool Val2>
00167 struct OR_bool {
00168 enum { RET = (Val1 || Val2) };
00169 };
00171 template<bool Val1, bool Val2>
00172 struct XOR_bool {
00173 enum { RET = (Val1 ^ Val2) };
00174 };
00176
00177
00178
00179
00180 #if EXMAT_VC6
00181
00182
00185 template<bool Condition, class ThenType, class ElseType>
00186 struct IF
00187 {
00188 template<bool Condition>
00189 struct selector {
00190 typedef ThenType SELECT_CLASS;
00191 };
00192
00193 template<>
00194 struct selector<false> {
00195 typedef ElseType SELECT_CLASS;
00196 };
00197
00198 typedef selector<Condition>::SELECT_CLASS RET;
00199 };
00200 #else
00201 namespace PNS {
00202 struct SelectThen {
00203 template<class ThenType, class ElseType>
00204 struct Result {
00205 typedef ThenType RET;
00206 };
00207 };
00208 struct SelectElse {
00209 template<class ThenType, class ElseType>
00210 struct Result {
00211 typedef ElseType RET;
00212 };
00213 };
00214 template<bool Condition>
00215 struct ChooseSelector {
00216 typedef SelectThen RET;
00217 };
00218 template<>
00219 struct ChooseSelector<false> {
00220 typedef SelectElse RET;
00221 };
00222 };
00223
00225
00228 template<bool Condition, class ThenType, class ElseType>
00229 class IF {
00230 typedef typename ::exmat::PNS::ChooseSelector<Condition>::RET Selector;
00231 public:
00232
00233
00234 typedef typename Selector::template Result<ThenType, ElseType>::RET RET;
00235 };
00236 #endif
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 const int DEFAULT = ~(~0u >> 1);
00251 const int nilValue = DEFAULT+1;
00252 struct NilCase {
00253 enum { tag = nilValue };
00254 typedef NilCase RET;
00255 };
00256
00257 template<int tag_, class Type_, class Next_=NilCase>
00258 struct CASE {
00259 enum { tag = tag_ };
00260 typedef Type_ Type;
00261 typedef Next_ Next;
00262 };
00263
00264 template<int tag, class Case>
00265 class SWITCH {
00266 typedef typename Case::Next NextCase;
00267 enum {
00268 caseTag = Case::tag,
00269 nextTag = NextCase::tag,
00270 found = (caseTag == tag || caseTag == DEFAULT )
00271 };
00272 typedef typename
00273 IF<(nextTag == nilValue),
00274 NilCase,
00275 SWITCH<tag, NextCase>
00276 >::RET NextSwitch;
00277 public:
00278 typedef typename
00279 IF<(found != 0),
00280 typename Case::Type,
00281 typename NextSwitch::RET
00282 >::RET RET;
00283 };
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 namespace PNS {
00296 template<class Statement>
00297 struct STOP {
00298 typedef Statement RET;
00299 EXMAT_INLINE2 static void exec() {};
00300 template<class Env> EXMAT_INLINE2 static void exec(Env&) {};
00301 };
00302 };
00303
00305 template<class Statement>
00306 struct WHILE {
00307 typedef typename
00308 IF<
00309 Statement::Condition,
00310 WHILE<typename Statement::Next>,
00311 PNS::STOP<Statement>
00312 >::RET TMP;
00313 typedef typename TMP::RET RET;
00314 };
00315
00316
00318 template<class Statement>
00319 class DO {
00320 typedef typename Statement::Next NewStatement;
00321 typedef typename IF<
00322 NewStatement::Condition,
00323 DO<NewStatement>,
00324 ::exmat::PNS::STOP<NewStatement>
00325 >::RET TMP;
00326 public:
00327 typedef typename TMP::RET RET;
00328 };
00329
00330
00332 template<class Statement>
00333 struct EWHILE {
00334 EXMAT_INLINE2 static void exec() {
00335 IF<
00336 Statement::Condition,
00337 Statement,
00338 PNS::STOP<Statement>
00339 >::RET::exec();
00340 typedef typename Statement::Next next;
00341 IF<
00342 Statement::Condition,
00343 EWHILE<next>,
00344 PNS::STOP<Statement>
00345 >::RET::exec();
00346 }
00347 };
00348
00349
00351 template<class Statement>
00352 struct EWHILE1 {
00353 template<class Env>
00354 EXMAT_INLINE2 static void exec(Env& env) {
00355 IF<
00356 Statement::Condition,
00357 Statement,
00358 ::exmat::PNS::STOP<Statement>
00359 >::RET::exec(env);
00360 typedef typename Statement::Next next;
00361 IF<
00362 Statement::Condition,
00363 EWHILE1<next>,
00364 ::exmat::PNS::STOP<Statement>
00365 >::RET::exec(env);
00366 }
00367 };
00368
00369
00370
00372 template<int N1, int N2>
00373 class MIN {
00374 private:
00375 typedef typename
00376 IF< LESS<N1,N2>::RET,
00377 Int2Type<N1>, Int2Type<N2>
00378 >::RET SmallerType;
00379 public:
00380 enum { RET = SmallerType::RET };
00381 };
00383 template<int N1, int N2>
00384 class MAX {
00385 private:
00386 typedef typename
00387 IF< GREATER<N1,N2>::RET,
00388 Int2Type<N1>, Int2Type<N2>
00389 >::RET BiggerType;
00390 public:
00391 enum { RET = BiggerType::RET };
00392 };
00393
00394
00395
00396 namespace PNS {
00397 template<int n_, int p_>
00398 struct SQRT_STAT {
00399 enum {
00400 p = p_,
00401 n = n_
00402 };
00403 typedef SQRT_STAT<n-p-2, p+2> Next;
00404 enum { Condition = n >= 0 };
00405 };
00406 }
00408 template<int n>
00409 struct SQRT {
00410 enum {
00411 p = DO<
00412 PNS::SQRT_STAT<n,-1>
00413 >::RET::p,
00414 RET = p/2
00415 };
00416 };
00417
00418
00419
00420 namespace PNS {
00421 template<int m_, unsigned int n_, int num_=1>
00422 struct POW_STAT {
00423 typedef POW_STAT<m_, n_-1, num_*m_> Next;
00424 enum { Condition = n_ > 0 };
00425 enum { RET = num_ };
00426 };
00427 }
00429 template<int m, unsigned int n>
00430 class POW {
00431 typedef typename
00432 IF< n == 0,
00433 Int2Type<1>,
00434 typename DO<
00435 ::exmat::PNS::POW_STAT<m,MAX<n,1>::RET >
00436 >::RET
00437 >::RET RetType;
00438 public:
00439 enum {
00440 RET = RetType::RET
00441 };
00442 };
00443 #if HAVE_PARTIAL_SPECIALIZATION
00444 template<int m> class POW<m, 0> { public: enum { RET = 1 }; };
00445 template<int m> class POW<m, 1> { public: enum { RET = m }; };
00446 template<int m> class POW<m, 2> { public: enum { RET = m*m }; };
00447 template<int m> class POW<m, 3> { public: enum { RET = m*m*m }; };
00448 #endif // HAVE_PARTIAL_SPECIALIZATION
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00491 template<unsigned int num, unsigned int n=sizeof(int)*4/2>
00492 class IsPowOf2 {
00493 typedef typename
00494 IF< n==1,
00495 Int2Type<false>,
00496 typename
00497 IF< num == POW<2,n>::RET,
00498 Int2Type<true>,
00499 IsPowOf2<num, n-1>
00500 >::RET>::RET RetType;
00501 public:
00502 enum {
00503 RET = RetType::RET
00504 };
00505 };
00506 template<> class IsPowOf2<8, sizeof(int)*4/2> {
00507 public: enum { RET = true };
00508 };
00509 template<> class IsPowOf2<16, sizeof(int)*4/2> {
00510 public: enum { RET = true };
00511 };
00512 template<> class IsPowOf2<32, sizeof(int)*4/2> {
00513 public: enum { RET = true };
00514 };
00515 template<> class IsPowOf2<64, sizeof(int)*4/2> {
00516 public: enum { RET = true };
00517 };
00518
00519
00520
00521
00522
00523
00524
00525 namespace BITSET {
00526
00527 enum { BitsUnitLength = sizeof(int) };
00528
00529 struct NullBITS {
00530 typedef NullBITS Next;
00531 enum { BitsUnit = 0, Level = -1 };
00532 };
00533
00534 template<int B=0, class N=NullBITS>
00535 struct BITS {
00536 typedef N Next;
00537 enum {
00538 BitsUnit = B,
00539 Level = Next::Level+1
00540 };
00541
00542 };
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 template<bool b1> struct BIT1 {
00558 typedef BITS<b1> RET; };
00559 template<bool b1,bool b2> struct BIT2 {
00560 typedef BITS<b1+(b2<<1)> RET; };
00561 template<bool b1,bool b2,bool b3> struct BIT3 {
00562 typedef BITS<b1+(b2<<1)+(b3<<2)> RET; };
00563 template<bool b1,bool b2,bool b3,bool b4> struct BIT4 {
00564 typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)> RET; };
00565 template<bool b1,bool b2,bool b3,bool b4,bool b5> struct BIT5 {
00566 typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)> RET; };
00567 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6> struct BIT6 {
00568 typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)> RET; };
00569 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6,bool b7> struct BIT7 {
00570 typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)+(b7<<6)> RET; };
00571 template<bool b1,bool b2,bool b3,bool b4,bool b5,bool b6,bool b7,bool b8> struct BIT8 {
00572 typedef BITS<b1+(b2<<1)+(b3<<2)+(b4<<3)+(b5<<4)+(b6<<5)+(b7<<6)+(b8<<7)> RET; };
00573
00574 template<class Bits, int I>
00575 class GetBitAt {
00576 template<int b, int i> struct BitAtInt
00577 { enum { RET = (1 << i) & b }; };
00578
00579 typedef typename IF<EQUAL<I/32, Bits::Level>::RET,
00580 BitAtInt<Bits::BitsUnit, I%BitsUnitLength>,
00581 GetBitAt<TTYPENAME Bits::Next, I%BitsUnitLength>
00582 >::RET RetT;
00583 public:
00584 enum {
00585 RET = (RetT::RET > 0 ? 1 : 0)
00586 };
00587 };
00588
00590 template<class Bits, int I, bool Bit>
00591 class SetBitAt {
00592 enum {
00593 I2 = I%BitsUnitLength,
00594 NewBitsUnit = (!Bit << I2) ^ (Bits::BitsUnit | (1 << I2))
00595 };
00596 #if EXMAT_VC6
00597 public:
00598 #endif // EXMAT_VC6
00599 template<class Bits_, int I_, bool Bit_>
00600 struct Append {
00601 enum {
00602 Lp1 = Bits_::Level+1,
00603 BitsUnit = Bit_ << I_%BitsUnitLength
00604 };
00605 typedef typename IF<GREATER<I_/BitsUnitLength, Lp1>::RET,
00606 Append<BITS<0, Bits_>, I_, Bit_>,
00607 Type2Type<BITS<BitsUnit, Bits_> >
00608 >::RET RetT_;
00609 typedef typename RetT_::RET RET;
00610 };
00611 #if EXMAT_VC6
00612 private:
00613 #endif // EXMAT_VC6
00614 typedef typename IF<GREATER<I/BitsUnitLength, Bits::Level>::RET,
00615 Type2Type<TTYPENAME Bits::Next>,
00616 TTYPENAME IF<EQUAL<I/BitsUnitLength, Bits::Level>::RET,
00617 Type2Type<TTYPENAME Bits::Next>,
00618 SetBitAt<TTYPENAME Bits::Next,I,Bit>
00619 >::RET>::RET Helper;
00620
00621 typedef typename IF<GREATER<I/BitsUnitLength, Bits::Level>::RET,
00622 Append<Bits, I, Bit>,
00623 TTYPENAME IF<EQUAL<I/BitsUnitLength, Bits::Level>::RET,
00624 Type2Type<BITS<NewBitsUnit, TTYPENAME Helper::RET> >,
00625 Type2Type<BITS<Bits::BitsUnit, TTYPENAME Helper::RET> >
00626 >::RET>::RET RetT;
00627
00628 public:
00629 typedef typename RetT::RET RET;
00630 };
00631
00632 template<class Bits1, class Bits2>
00633 class OR {
00634 enum {
00635 LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00636 ResultUnit =
00637 (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) |
00638 (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00639 };
00640 typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00641 TTYPENAME Bits1::Next, Bits1
00642 >::RET B1N;
00643 typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00644 TTYPENAME Bits2::Next, Bits2
00645 >::RET B2N;
00646 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00647 Type2Type<BITS<ResultUnit> >,
00648 OR<B1N, B2N>
00649 >::RET Helper;
00650 public:
00651 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00652 TTYPENAME Helper::RET,
00653 BITS<ResultUnit, TTYPENAME Helper::RET>
00654 >::RET RET;
00655 };
00656
00657 template<class Bits1, class Bits2>
00658 class XOR {
00659 enum {
00660 LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00661 ResultUnit =
00662 (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) ^
00663 (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00664 };
00665 typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00666 TTYPENAME Bits1::Next, Bits1
00667 >::RET B1N;
00668 typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00669 TTYPENAME Bits2::Next, Bits2
00670 >::RET B2N;
00671 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00672 Type2Type<BITS<ResultUnit> >,
00673 XOR<B1N, B2N>
00674 >::RET Helper;
00675 public:
00676 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00677 TTYPENAME Helper::RET,
00678 BITS<ResultUnit, TTYPENAME Helper::RET>
00679 >::RET RET;
00680 };
00681
00682 template<class Bits1, class Bits2>
00683 class AND {
00684 enum {
00685 LargerLevel = MAX<Bits1::Level, Bits2::Level>::RET,
00686 ResultUnit =
00687 (Bits1::Level == LargerLevel ? Bits1::BitsUnit : 0) &
00688 (Bits2::Level == LargerLevel ? Bits2::BitsUnit : 0)
00689 };
00690 typedef typename IF<EQUAL<Bits1::Level,LargerLevel>::RET,
00691 TTYPENAME Bits1::Next, Bits1
00692 >::RET B1N;
00693 typedef typename IF<EQUAL<Bits2::Level,LargerLevel>::RET,
00694 TTYPENAME Bits2::Next, Bits2
00695 >::RET B2N;
00696 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00697 Type2Type<BITS<ResultUnit> >,
00698 AND<B1N, B2N>
00699 >::RET Helper;
00700 public:
00701 typedef typename IF<EQUAL<LargerLevel, 0>::RET,
00702 TTYPENAME Helper::RET,
00703 BITS<ResultUnit, TTYPENAME Helper::RET>
00704 >::RET RET;
00705 };
00706
00707 template<class Bits>
00708 class NOT {
00709 enum { ResultUnit = ~Bits::BitsUnit };
00710 typedef typename IF<EQUAL<Bits::Level, 0>::RET,
00711 Type2Type<BITS<ResultUnit> >,
00712 NOT<TTYPENAME Bits::Next>
00713 >::RET Helper;
00714 public:
00715 typedef typename IF<EQUAL<Bits::Level, 0>::RET,
00716 TTYPENAME Helper::RET,
00717 BITS<ResultUnit, TTYPENAME Helper::RET>
00718 >::RET RET;
00719 };
00720
00721 };
00722
00723 }
00724
00725 #ifdef _MSC_VER
00726 # pragma warning( pop )
00727 #endif // _MSC_VER
00728
00729 #endif // _EXMAT_METAPROGRAMMING_H