FXGenericTools.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                        Tools for generic programming                          *
00004 *                                                                               *
00005 *********************************************************************************
00006 *        Copyright (C) 2003-2009 by Niall Douglas.   All Rights Reserved.       *
00007 *       NOTE THAT I DO NOT PERMIT ANY OF MY CODE TO BE PROMOTED TO THE GPL      *
00008 *********************************************************************************
00009 * This code is free software; you can redistribute it and/or modify it under    *
00010 * the terms of the GNU Library General Public License v2.1 as published by the  *
00011 * Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
00012 * "upgrade" this code to the GPL without my prior written permission.           *
00013 * Please consult the file "License_Addendum2.txt" accompanying this file.       *
00014 *                                                                               *
00015 * This code is distributed in the hope that it will be useful,                  *
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                          *
00018 *********************************************************************************
00019 * $Id:                                                                          *
00020 ********************************************************************************/
00021 
00022 #ifndef FXGENERICTOOLS_H
00023 #define FXGENERICTOOLS_H
00024 
00025 #include "FXString.h"
00026 #include "FXPolicies.h"
00027 #include "FXException.h"
00028 #include "FXPath.h"
00029 #include <typeinfo>
00030 #include <assert.h>
00031 
00032 namespace FX {
00033 
00039 namespace Generic {
00054 // MSVC doesn't define type_info within namespace std :(
00055 #ifdef _MSC_VER
00056 typedef ::type_info type_info;
00057 #else
00058 typedef std::type_info type_info;
00059 #endif
00060 
00061 #ifndef HAVE_CPP0XSTATICASSERT
00062 template<bool> struct StaticAssert;
00063 template<> struct StaticAssert<true>
00064 {
00065     StaticAssert() { }
00066 };
00067 #define FXSTATIC_ASSERT2(expr, msg) \
00068     FX::Generic::StaticAssert<(expr)!=0> ERROR_##msg
00069 
00079 #define FXSTATIC_ASSERT(expr, msg) \
00080 { \
00081     FXSTATIC_ASSERT2(expr, msg); \
00082 }
00083 
00084 template<typename foo> struct StaticError;
00085 #else
00086 #define FXSTATIC_ASSERT(expr, msg) static_assert((expr)!=0, #msg )
00087 #define FXSTATIC_ASSERT2(expr, msg) static_assert((expr)!=0, #msg )
00088 #endif
00089 
00094 struct NullType { };
00101 template<int n> struct IntToType { static const int value=n; };
00107 template<typename type> struct TypeToType { typedef type value; };
00112 template<bool v, typename type=NullType> struct Boolean { static const bool value=v; };
00113 
00122 template<bool v, typename A, typename B> struct select
00123 {
00124     typedef A value;
00125 };
00126 template<typename A, typename B> struct select<false, A, B>
00127 {
00128     typedef B value;
00129 };
00134 template<typename A, typename B> struct sameType
00135 {
00136     static const bool value=false;
00137 };
00138 template<typename T> struct sameType<T, T>
00139 {
00140     static const bool value=true;
00141 };
00146 template<typename type> struct addRef { typedef type &value; };
00147 template<typename type> struct addRef<type &> { typedef type value; };
00148 template<> struct addRef<void> { typedef void value; };
00149 template<> struct addRef<const void> { typedef const void value; };
00154 template<typename type> struct addConstRef { typedef const type &value; };
00155 template<typename type> struct addConstRef<type &> { typedef typename addConstRef<type>::value value; };
00156 template<typename type> struct addConstRef<const type> { typedef typename addConstRef<type>::value value; };
00157 template<typename type> struct addConstRef<const type &> { typedef const type &value; };
00158 template<> struct addConstRef<void> { typedef void value; };
00159 
00160 namespace convertiblePrivate {
00161     struct TwoChar { char foo[2]; };
00162     template<typename to, typename from> struct impl
00163     {
00164         static from makeFrom();
00165         static TwoChar test(...);
00166         static    char test(to);
00167     };
00168 }
00169 #ifdef _MSC_VER
00170 #pragma warning(push)
00171 #pragma warning(disable: 4244)  // possible loss of data
00172 #pragma warning(disable: 4800)  // forcing value to bool true or false
00173 #endif
00174 
00178 template<typename to, typename from> struct convertible
00179 {
00180 private:
00181     typedef typename addConstRef<to>::value refTo;
00182     typedef typename addConstRef<from>::value refFrom;
00183     typedef convertiblePrivate::impl<refTo, refFrom> impl;
00184 public:
00185     static const bool value=sizeof(impl::test(impl::makeFrom()))==sizeof(char);
00186 };
00187 template<typename T> struct convertible<void, T> { static const bool value=false; };
00188 template<typename T> struct convertible<T, void> { static const bool value=false; };
00189 template<> struct convertible<void, void> { static const bool value=true; };
00190 #ifdef _MSC_VER
00191 #pragma warning(pop)
00192 #endif
00193 
00202 template<typename ptr> struct lessIndir
00203 {
00204     typedef ptr value;
00205     static const bool failed=true;
00206 };
00207 template<typename ptr> struct lessIndir<ptr *>
00208 {
00209     typedef ptr value;
00210     static const bool failed=false;
00211 };
00212 template<typename ptr> struct lessIndir<const ptr *>
00213 {
00214     typedef ptr value;
00215     static const bool failed=false;
00216 };
00217 template<typename ptr> struct lessIndir<volatile ptr *>
00218 {
00219     typedef ptr value;
00220     static const bool failed=false;
00221 };
00222 template<typename ptr> struct lessIndir<const volatile ptr *>
00223 {
00224     typedef ptr value;
00225     static const bool failed=false;
00226 };
00227 template<typename ptr> struct lessIndir<ptr &>
00228 {
00229     typedef ptr value;
00230     static const bool failed=false;
00231 };
00232 template<typename ptr> struct lessIndir<const ptr &>
00233 {
00234     typedef ptr value;
00235     static const bool failed=false;
00236 };
00237 template<typename ptr> struct lessIndir<volatile ptr &>
00238 {
00239     typedef ptr value;
00240     static const bool failed=false;
00241 };
00242 template<typename ptr> struct lessIndir<const volatile ptr &>
00243 {
00244     typedef ptr value;
00245     static const bool failed=false;
00246 };
00251 template<typename type> struct indirs { static const int value=0; };
00252 template<typename type> struct indirs<type &> { static const int value=1+indirs<type>::value; };
00253 template<typename type> struct indirs<const type &> { static const int value=1+indirs<type>::value; };
00254 template<typename type> struct indirs<volatile type &> { static const int value=1+indirs<type>::value; };
00255 template<typename type> struct indirs<const volatile type &> { static const int value=1+indirs<type>::value; };
00256 template<typename type> struct indirs<type *> { static const int value=1+indirs<type>::value; };
00257 template<typename type> struct indirs<const type *> { static const int value=1+indirs<type>::value; };
00258 template<typename type> struct indirs<volatile type *> { static const int value=1+indirs<type>::value; };
00259 template<typename type> struct indirs<const volatile type *> { static const int value=1+indirs<type>::value; };
00264 template<typename ptr> struct leastIndir { typedef ptr value; };
00265 template<typename ptr> struct leastIndir<ptr *> { typedef typename leastIndir<ptr>::value value; };
00266 template<typename ptr> struct leastIndir<const ptr *> { typedef typename leastIndir<ptr>::value value; };
00267 template<typename ptr> struct leastIndir<volatile ptr *> { typedef typename leastIndir<ptr>::value value; };
00268 template<typename ptr> struct leastIndir<const volatile ptr *> { typedef typename leastIndir<ptr>::value value; };
00269 template<typename ptr> struct leastIndir<ptr &> { typedef typename leastIndir<ptr>::value value; };
00270 template<typename ptr> struct leastIndir<const ptr &> { typedef typename leastIndir<ptr>::value value; };
00271 template<typename ptr> struct leastIndir<volatile ptr &> { typedef typename leastIndir<ptr>::value value; };
00272 template<typename ptr> struct leastIndir<const volatile ptr &> { typedef typename leastIndir<ptr>::value value; };
00273 
00274 #if defined(_MSC_VER) && _MSC_VER>=1400
00275 namespace msvc_typeof_impl {
00276     /* This is a fusion of Igor Chesnokov's method (http://rsdn.ru/forum/src/1094305.aspx)
00277     and Steven Watanabe's method (http://lists.boost.org/Archives/boost/2006/12/115006.php)
00278 
00279     How it works:
00280     C++ allows template type inference for templated function parameters but nothing else.
00281     What we do is to pass the expression sent to typeof() into the templated function vartypeID()
00282     as its parameter, thus extracting its type. The big problem traditionally now is how to get
00283     that type out of the vartypeID() instance, and here's how we do it:
00284         1. unique_type_id() returns a monotonically increasing integer for every unique type
00285            passed to it during this compilation unit. It also specialises an instance of
00286            msvc_extract_type<unique_type_id, type>::id2type_impl<true>.
00287         2. vartypeID() returns a sized<unique_type_id> for the type where
00288            sizeof(sized<unique_type_id>)==unique_type_id. We vector through sized as a means
00289            of returning the unique_type_id at compile time rather than runtime.
00290         3. msvc_extract_type<unique_type_id> then extracts the type by using a bug in MSVC to
00291            reselect the specialised child type (id2type_impl<true>) from within the specialisation
00292            of itself originally performed by the above instance of unique_type_id. This bug works
00293            because when MSVC calculated the signature of the specialised
00294            msvc_extract_type<unique_type_id, type>::id2type_impl<true>, it does not include the
00295            value of type in the signature of id2type_impl<true>. Therefore when we reselect
00296            msvc_extract_type<unique_type_id>::id2type_impl<true> it erroneously returns the one
00297            already in its list of instantiated types rather than correctly generating a newly
00298            specialised msvc_extract_type<unique_type_id, msvc_extract_type_default_param>::id2type_impl<true>
00299 
00300     This bug allows the impossible and gives us a working typeof() in MSVC. Hopefully Microsoft
00301     won't fix this bug until they implement a native typeof.
00302     */
00303 
00304     struct msvc_extract_type_default_param {};
00305     template<int ID, typename T = msvc_extract_type_default_param> struct msvc_extract_type;
00306 
00307     template<int ID> struct msvc_extract_type<ID, msvc_extract_type_default_param>
00308     {
00309         template<bool> struct id2type_impl; 
00310 
00311         typedef id2type_impl<true> id2type; 
00312     };
00313 
00314     template<int ID, typename T> struct msvc_extract_type : msvc_extract_type<ID, msvc_extract_type_default_param> 
00315     { 
00316         template<> struct id2type_impl<true> //VC8.0 specific bugfeature 
00317         { 
00318             typedef T type; 
00319         }; 
00320         template<bool> struct id2type_impl; 
00321 
00322         typedef id2type_impl<true> id2type; 
00323     }; 
00324 
00325 
00326     template<int N> class CCounter;
00327 
00328     // TUnused is required to force compiler to recompile CCountOf class
00329     template<typename TUnused, int NTested = 0> struct CCountOf
00330     {
00331         enum
00332         {
00333             __if_exists(CCounter<NTested>) { count = CCountOf<TUnused, NTested + 1>::count }
00334             __if_not_exists(CCounter<NTested>) { count = NTested }
00335         };
00336     };
00337 
00338     template<class TTypeReg, class TUnused, int NValue> struct CProvideCounterValue { enum { value = NValue }; };
00339 
00340     // type_id
00341     #define unique_type_id(type) \
00342         (CProvideCounterValue< \
00343             /*register TYPE--ID*/ typename msvc_extract_type<CCountOf<type >::count, type>::id2type, \
00344             /*increment compile-time Counter*/ CCounter<CCountOf<type >::count>, \
00345             /*pass value of Counter*/CCountOf<type >::count \
00346          >::value)
00347 
00348     // Lets type_id() be > than 0
00349     class __Increment_type_id { enum { value = unique_type_id(__Increment_type_id) }; };
00350 
00351     // vartypeID() returns a type with sizeof(type_id)
00352     template<int NSize> class sized { char m_pad[NSize]; };
00353     template<typename T> typename sized<unique_type_id(T)> vartypeID(T&);
00354     template<typename T> typename sized<unique_type_id(const T)> vartypeID(const T&);
00355     template<typename T> typename sized<unique_type_id(volatile  T)> vartypeID(volatile T&);
00356     template<typename T> typename sized<unique_type_id(const volatile T)> vartypeID(const volatile T&);
00357 }
00358 
00359 #define typeof(expression) FX::Generic::msvc_typeof_impl::msvc_extract_type<sizeof(FX::Generic::msvc_typeof_impl::vartypeID(expression))>::id2type::type
00360 #endif
00361 
00365 class typeInfoBase
00366 {
00367     FXString decorated, readable;
00368 public:
00369     typeInfoBase() { }
00371     typeInfoBase(const type_info &ti) :
00372 #ifdef _MSC_VER
00373         decorated(ti.raw_name()), readable(ti.name())
00374 #elif defined(__GNUC__) || defined(__DMC__)
00375         decorated(ti.name()), readable(fxdemanglesymbol(ti.name()))
00376 #else
00377 #error Method of demangling RTTI unknown
00378 #endif
00379         {
00380             assert(!decorated.empty());
00381         }
00383     bool operator!() const throw() { return !!decorated.empty(); }
00385     bool operator==(const typeInfoBase &o) const { return (decorated==o.decorated)!=0; }
00387     bool operator!=(const typeInfoBase &o) const { return (decorated!=o.decorated)!=0; }
00389     const FXString &name() const { return readable; }
00391     const FXString &mangled() const { return decorated; }
00393     FXString asIdentifier() const
00394     {
00395         FXString ret(readable);
00396         ret.substitute('<', '_'); ret.substitute('>', '_'); ret.substitute(',', '_'); ret.substitute(':', '_');
00397         return ret;
00398     }
00400     FXString asLeafIdentifier() const
00401     {
00402         FXint rpos=readable.rfind(':'); if(-1==rpos) rpos=readable.rfind(' ');
00403         FXString ret(readable.mid(rpos+1));
00404         return ret;
00405     }
00406     // These defined in fxutils.cpp
00407     friend FXAPI FXStream &operator<<(FXStream &s, const typeInfoBase &i);
00408     friend FXAPI FXStream &operator>>(FXStream &s, typeInfoBase &i);
00409 };
00427 template<typename type> class typeInfo : public typeInfoBase
00428 {
00429 public:
00430     typeInfo(const type_info &ti=typeid(type)) : typeInfoBase(ti) { }
00431 };
00493 template<typename type,
00494     template<class> class ownershipPolicy=FX::Pol::destructiveCopy>
00495 class ptr : public ownershipPolicy<type>
00496 {
00497     typedef ownershipPolicy<type> op;
00498 public:
00500     ptr(type *data=0) : op(data) { }
00501     ptr(const ptr &o) : op(o) { }
00503     ptr &operator=(type *data) { PtrReset(*this, data); return *this; }
00504     type &operator *() { assert(PtrPtr(*this)); return *PtrPtr(*this); }
00505     const type &operator *() const { assert(PtrPtr(*this)); return *PtrPtr(*this); }
00506     type *operator->()
00507     {
00508         type *ret=PtrPtr(*this);
00509         if(!ret)
00510         {
00511             assert(ret);
00512         }
00513         return ret;
00514     }
00515     const type *operator->() const
00516     {
00517         const type *ret=PtrPtr(*this);
00518         if(!ret)
00519         {
00520             assert(ret);
00521         }
00522         return ret;
00523     }
00525     friend type *PtrRelease(ptr &p)
00526     {
00527         type *ret=PtrRef(p);
00528         PtrRef(p)=0;
00529         return ret;
00530     }
00532     friend void PtrReset(ptr &p, type *data)
00533     {
00534         p=ptr(data);
00535     }
00536     template<typename T> bool operator==(const ptr<T> &o) const { return PtrRef(*this)==PtrRef(o); }
00537     template<typename T> bool operator==(T *o) const { return PtrRef(*this)==o; }
00538     // Workaround to implement if(sp)
00539 private:
00540     struct Tester
00541     {
00542     private:
00543         void operator delete(void *);
00544     };
00545 public:
00546     operator Tester *() const
00547     {
00548         if(!*this) return 0;
00549         static Tester t;
00550         return &t;
00551     }
00552 
00553     // For if(!sp) 
00554     bool operator!() const { return PtrRef(*this)==0; }
00555     template<typename T> bool operator!=(const ptr<T> &o) const { return !(*this==o); }
00556     template<typename T> bool operator!=(T *o) const { return !(*this==o); }
00557 };
00558 
00589 namespace TL
00590 {
00595     template<typename A, typename B> struct item
00596     {
00598         typedef A value;
00600         typedef B next;
00601     };
00607     template<typename T1 =NullType, typename T2 =NullType, typename T3 =NullType, typename T4 =NullType,
00608              typename T5 =NullType, typename T6 =NullType, typename T7 =NullType, typename T8 =NullType,
00609              typename T9 =NullType, typename T10=NullType, typename T11=NullType, typename T12=NullType,
00610              typename T13=NullType, typename T14=NullType, typename T15=NullType, typename T16=NullType>
00611     struct create
00612     {
00613     private:
00614         typedef typename create<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value temp;
00615     public:
00616         typedef item<T1, temp> value;
00617     };
00618     template<> struct create<> { typedef NullType value; };
00628     template<class typelist> struct length
00629     {
00630         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00631     };
00632     template<> struct length<NullType> { static const int value=0; };
00633     template<class A, class B> struct length< item<A, B> >
00634     {
00635         static const int value=1+length<B>::value;
00636     };
00641     template<class typelist, FXuint idx> struct at { typedef NullType value; };
00642     template<class A, class B> struct at<item<A, B>, 0> { typedef A value; };
00643     template<class A, class B, FXuint idx> struct at<item<A, B>, idx>
00644     {
00645         typedef typename at<B, idx-1>::value value;
00646     };
00651     template<class typelist, FXuint idx> struct atC
00652     {
00653         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Out_Of_Bounds_Or_Not_A_TypeList);
00654     };
00655     template<class A, class B> struct atC<item<A, B>, 0> { typedef A value; };
00656     template<class A, class B, FXuint idx> struct atC<item<A, B>, idx>
00657     {
00658         typedef typename atC<B, idx-1>::value value;
00659     };
00664     template<class typelist, typename type> struct find
00665     {
00666         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00667     };
00668     template<typename type> struct find<NullType, type> { static const int value=-1; };
00669     template<typename type, class next> struct find<item<type, next>, type> { static const int value=0; };
00670     template<typename A, class next, typename type> struct find<item<A, next>, type>
00671     {
00672     private:
00673         static const int temp=find<next, type>::value;
00674     public:
00675         static const int value=(temp==-1 ? -1 : 1+temp);
00676     };
00681     template<class typelist, typename type> struct findC
00682     {
00683         static const int value=find<typelist, type>::value;
00684     private:
00685         FXSTATIC_ASSERT2(value!=-1, ERROR_Type_Not_Found);
00686     };
00691     template<class typelist, typename type> struct findParent
00692     {
00693         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00694     };
00695     template<typename type> struct findParent<NullType, type> { static const int value=-1; };
00696     template<typename type, class next> struct findParent<item<type, next>, type> { static const int value=0; };
00697     template<typename A, class next, typename type> struct findParent<item<A, next>, type>
00698     {
00699     private:
00700         static const bool isSubclass=convertible<A, type>::value;
00701         static const int temp=isSubclass ? 0 : findParent<next, type>::value;
00702     public:
00703         static const int value=(temp==-1 ? -1 : 1+temp-isSubclass);
00704     };
00709     template<class typelist, typename type> struct findParentC
00710     {
00711         static const int value=findParent<typelist, type>::value;
00712     private:
00713         FXSTATIC_ASSERT2(value!=-1, ERROR_Type_Not_Found);
00714     };
00719     template<class typelist, typename type> struct append
00720     {
00721         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00722     };
00723     template<> struct append<NullType, NullType> { typedef NullType value; };
00724     template<typename type> struct append<NullType, type> { typedef typename create<type>::value value; };
00725     template<typename A, class next> struct append<NullType, item<A, next> >
00726     {
00727         typedef item<A, next> value;
00728     };
00729     template<typename A, class next, typename type> struct append<item<A,next>, type>
00730     {
00731         typedef item<A, typename append<next, type>::value> value;
00732     };
00737     template<class typelist, typename type> struct remove
00738     {
00739         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00740     };
00741     template<typename type> struct remove<NullType, type> { typedef NullType value; };
00742     template<typename type, class next> struct remove<item<type, next>, type> { typedef next value; };
00743     template<typename A, class next, typename type> struct remove<item<A, next>, type>
00744     {
00745         typedef item<A, typename remove<next, type>::value> value;
00746     };
00747     namespace numberRangePrivate {
00748         template<int no, template<int> class instance, int top> struct Impl
00749         {
00750             typedef item<instance<top-no>, typename Impl<no-1, instance, top>::value> value;
00751         };
00752         template<template<int> class instance, int top> struct Impl<0, instance, top>
00753         {
00754             typedef NullType value;
00755         };
00756     }
00766     template<int no, template<int> class instance=IntToType> struct numberRange
00767     {
00768         typedef typename numberRangePrivate::Impl<no, instance, no>::value value;
00769     };
00776     template<typename typelist, template<class> class instance> struct apply
00777     {
00778         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00779     };
00780     template<typename type, class next, template<class> class instance> struct apply<item<type, next>, instance>
00781     {
00782         typedef item<instance<type>, typename apply<next, instance>::value> value;
00783     };
00784     template<template<class> class instance> struct apply<NullType, instance>
00785     {
00786         typedef NullType value;
00787     };
00799     template<typename typelist, template<class> class filt> struct filter
00800     {
00801         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00802     };
00803     template<typename type, class next, template<class> class filt> struct filter<item<type, next>, filt>
00804     {
00805     private:
00806         typedef typename filter<next, filt>::value nextfilter;
00807     public:
00808         typedef typename select<filt<type>::value, item<type, nextfilter>, nextfilter>::value value;
00809     };
00810     template<template<class> class filt> struct filter<NullType, filt>
00811     {
00812         typedef NullType value;
00813     };
00818     template<int no, typename type> struct replicate
00819     {
00820         typedef item<type, typename replicate<no-1, type>::value> value;
00821     };
00822     template<typename type> struct replicate<0, type>
00823     {
00824         typedef NullType value;
00825     };
00826 
00827 #if defined(_MSC_VER)
00828 #pragma warning(push)
00829 // Disable silly warning about class inheriting off itself
00830 #pragma warning(disable : 4584)
00831 #endif // _MSC_VER
00832 
00837     template<typename type> struct instanceHolderH
00838     {
00839         type value;
00841         instanceHolderH() { }
00843         template<typename P1> instanceHolderH(P1 p1) : value(p1) { }
00845         template<typename P1, typename P2> instanceHolderH(P1 p1, P2 p2) : value(p1, p2) { }
00847         template<typename P1, typename P2, typename P3> instanceHolderH(P1 p1, P2 p2, P3 p3) : value(p1, p2, p3) { }
00848     };
00849 
00850     namespace Private
00851     {
00852         template<int idx, class instance> struct instanceHHolder : public instance
00853         {   // Hold an indexed instantiation of a typelist member
00854             instanceHHolder() : instance() { }
00855             template<typename P1> explicit instanceHHolder(P1 p1) : instance(p1) { }
00856             template<typename P1, typename P2> explicit instanceHHolder(P1 p1, P2 p2) : instance(p1, p2) { }
00857             template<typename P1, typename P2, typename P3> explicit instanceHHolder(P1 p1, P2 p2, P3 p3) : instance(p1, p2, p3) { }
00858         };
00859     }
00889     template<typename typelist, template<class> class instance=instanceHolderH, int idx=0> struct instantiateH
00890     {
00891         FXSTATIC_ASSERT2((Boolean<false, typelist>::value), ERROR_Not_A_TypeList);
00892     };
00893     template<typename type, class next, template<class> class instance, int idx> struct instantiateH<item<type, next>, instance, idx>
00894         : public Private::instanceHHolder<idx, instance<type> >, public instantiateH<next, instance, idx+1>
00895     {
00897         instantiateH() : Private::instanceHHolder<idx, instance<type> >(), instantiateH<next, instance, idx+1>() { }
00899         template<typename P1> explicit instantiateH(P1 p1)
00900             : Private::instanceHHolder<idx, instance<type> >(p1), instantiateH<next, instance, idx+1>(p1) { }
00902         template<typename P1, typename P2> explicit instantiateH(P1 p1, P2 p2)
00903             : Private::instanceHHolder<idx, instance<type> >(p1, p2), instantiateH<next, instance, idx+1>(p1, p2) { }
00905         template<typename P1, typename P2, typename P3> explicit instantiateH(P1 p1, P2 p2, P3 p3)
00906             : Private::instanceHHolder<idx, instance<type> >(p1, p2, p3), instantiateH<next, instance, idx+1>(p1, p2, p3) { }
00907     };
00908     template<template<class> class instance, int idx> struct instantiateH<NullType, instance, idx>
00909     {
00910         instantiateH() { }
00911         template<typename P1> explicit instantiateH(P1 p1) { }
00912         template<typename P1, typename P2> explicit instantiateH(P1 p1, P2 p2) { }
00913         template<typename P1, typename P2, typename P3> explicit instantiateH(P1 p1, P2 p2, P3 p3) { }
00914     };
00915 
00916     namespace Private
00917     {
00918         // TODO: volatile specialisations & instantiateV
00919         template<int i, class container> struct accessInstantiateH
00920         {
00921             FXSTATIC_ASSERT2((Boolean<false, container>::value), ERROR_Not_An_InstantiateH_Container);
00922         };
00923         template<int i, typename typelist, template<class> class instance> struct accessInstantiateH<i, instantiateH<typelist, instance, 0> >
00924         {
00925             typedef instance<typename atC<typelist, i>::value> IdxType;
00926             typedef instantiateH<typelist, instance, 0> containerType;
00927             static IdxType &Get(containerType &c)
00928             {
00929                 return static_cast<instanceHHolder<i, IdxType> &>(c);
00930             }
00931         };
00932         template<int i, typename typelist, template<class> class instance> struct accessInstantiateH<i, const instantiateH<typelist, instance, 0> >
00933         {
00934             typedef instance<typename atC<typelist, i>::value> IdxTypeO;
00935             typedef const IdxTypeO IdxType;
00936             typedef const instantiateH<typelist, instance, 0> containerType;
00937             static IdxType &Get(const containerType &c)
00938             {
00939                 return static_cast<const instanceHHolder<i, IdxTypeO> &>(c);
00940             }
00941         };
00942     }
00949     template<int i, class container> typename Private::accessInstantiateH<i, container>::IdxType &instance(container &c)
00950     {
00951         return Private::accessInstantiateH<i, container>::Get(c);
00952     }
00953 #if defined(_MSC_VER)
00954 #pragma warning(pop) 
00955 #endif
00956 }
00957 #define FXTYPELIST1(P1) FX::Generic::TL::list<P1, FX::Generic::NullType>
00958 #define FXTYPELIST2(P1,P2) FX::Generic::TL::list<P1, FXTYPELIST1(P2) >
00959 #define FXTYPELIST3(P1,P2,P3) FX::Generic::TL::list<P1, FXTYPELIST2(P2,P3) >
00960 #define FXTYPELIST4(P1,P2,P3,P4) FX::Generic::TL::list<P1, FXTYPELIST3(P2,P3,P4) >
00961 #define FXTYPELIST5(P1,P2,P3,P4,P5) FX::Generic::TL::list<P1, FXTYPELIST4(P2,P3,P4,P5) >
00962 #define FXTYPELIST6(P1,P2,P3,P4,P5,P6) FX::Generic::TL::list<P1, FXTYPELIST5(P2,P3,P4,P5,P6) >
00963 #define FXTYPELIST7(P1,P2,P3,P4,P5,P6,P7) FX::Generic::TL::list<P1, FXTYPELIST6(P2,P3,P4,P5,P6,P7) >
00964 #define FXTYPELIST8(P1,P2,P3,P4,P5,P6,P7,P8) FX::Generic::TL::list<P1, FXTYPELIST7(P2,P3,P4,P5,P6,P7,P8) >
00965 #define FXTYPELIST9(P1,P2,P3,P4,P5,P6,P7,P8,P9) FX::Generic::TL::list<P1, FXTYPELIST8(P2,P3,P4,P5,P6,P7,P8,P9) >
00966 #define FXTYPELIST10(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10) \
00967     FX::Generic::TL::list<P1, FXTYPELIST9(P2,P3,P4,P5,P6,P7,P8,P9,P10) >
00968 #define FXTYPELIST11(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11) \
00969     FX::Generic::TL::list<P1, FXTYPELIST10(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11) >
00970 #define FXTYPELIST12(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12) \
00971     FX::Generic::TL::list<P1, FXTYPELIST11(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12) >
00972 #define FXTYPELIST13(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13) \
00973     FX::Generic::TL::list<P1, FXTYPELIST12(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13) >
00974 #define FXTYPELIST14(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14) \
00975     FX::Generic::TL::list<P1, FXTYPELIST13(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14) >
00976 #define FXTYPELIST15(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15) \
00977     FX::Generic::TL::list<P1, FXTYPELIST14(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15) >
00978 #define FXTYPELIST16(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16) \
00979     FX::Generic::TL::list<P1, FXTYPELIST15(P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16) >
00980 
01013 template<typename fn> struct FnInfo
01014 {
01015     typedef fn resultType;
01016     typedef NullType objectType;
01017     static const bool isConst=false;
01018     static const int arity=-1;
01019     typedef typename TL::create<resultType>::value asList;
01020 };
01021 template<typename R, typename O> struct FnInfo<R (O::*)()>
01022 {
01023     typedef R resultType;
01024     typedef O objectType;
01025     static const bool isConst=false;
01026     static const int arity=0;
01027     typedef typename TL::create<resultType>::value asList;
01028 };
01029 template<typename R, typename O> struct FnInfo<R (O::*)() const>
01030 {
01031     typedef R resultType;
01032     typedef O objectType;
01033     static const bool isConst=true;
01034     static const int arity=0;
01035     typedef typename TL::create<resultType>::value asList;
01036 };
01037 template<typename R> struct FnInfo<R (*)(void)>
01038 {
01039     typedef R resultType;
01040     typedef NullType objectType;
01041     static const bool isConst=false;
01042     static const int arity=0;
01043     typedef typename TL::create<resultType>::value asList;
01044 };
01045 template<typename R, typename O, typename P1> struct FnInfo<R (O::*)(P1)>
01046 {
01047     typedef R resultType;
01048     typedef O objectType;
01049     typedef P1 par1Type;
01050     static const bool isConst=false;
01051     static const int arity=1;
01052     typedef typename TL::create<resultType, par1Type>::value asList;
01053 };
01054 template<typename R, typename O, typename P1> struct FnInfo<R (O::*)(P1) const>
01055 {
01056     typedef R resultType;
01057     typedef O objectType;
01058     typedef P1 par1Type;
01059     static const bool isConst=true;
01060     static const int arity=1;
01061     typedef typename TL::create<resultType, par1Type>::value asList;
01062 };
01063 template<typename R, typename P1> struct FnInfo<R (*)(P1)>
01064 {
01065     typedef R resultType;
01066     typedef NullType objectType;
01067     typedef P1 par1Type;
01068     static const bool isConst=false;
01069     static const int arity=1;
01070     typedef typename TL::create<resultType, par1Type>::value asList;
01071 };
01072 template<typename R, typename O, typename P1, typename P2> struct FnInfo<R (O::*)(P1, P2)>
01073 {
01074     typedef R resultType;
01075     typedef O objectType;
01076     typedef P1 par1Type;
01077     typedef P2 par2Type;
01078     static const bool isConst=false;
01079     static const int arity=2;
01080     typedef typename TL::create<resultType, par1Type, par2Type>::value asList;
01081 };
01082 template<typename R, typename O, typename P1, typename P2> struct FnInfo<R (O::*)(P1, P2) const>
01083 {
01084     typedef R resultType;
01085     typedef O objectType;
01086     typedef P1 par1Type;
01087     typedef P2 par2Type;
01088     static const bool isConst=true;
01089     static const int arity=2;
01090     typedef typename TL::create<resultType, par1Type, par2Type>::value asList;
01091 };
01092 template<typename R, typename P1, typename P2> struct FnInfo<R (*)(P1, P2)>
01093 {
01094     typedef R resultType;
01095     typedef NullType objectType;
01096     typedef P1 par1Type;
01097     typedef P2 par2Type;
01098     static const bool isConst=false;
01099     static const int arity=2;
01100     typedef typename TL::create<resultType, par1Type, par2Type>::value asList;
01101 };
01102 template<typename R, typename O, typename P1, typename P2, typename P3> struct FnInfo<R (O::*)(P1, P2, P3)>
01103 {
01104     typedef R resultType;
01105     typedef O objectType;
01106     typedef P1 par1Type;
01107     typedef P2 par2Type;
01108     typedef P3 par3Type;
01109     static const bool isConst=false;
01110     static const int arity=3;
01111     typedef typename TL::create<resultType, par1Type, par2Type, par3Type>::value asList;
01112 };
01113 template<typename R, typename O, typename P1, typename P2, typename P3> struct FnInfo<R (O::*)(P1, P2, P3) const>
01114 {
01115     typedef R resultType;
01116     typedef O objectType;
01117     typedef P1 par1Type;
01118     typedef P2 par2Type;
01119     typedef P3 par3Type;
01120     static const bool isConst=true;
01121     static const int arity=3;
01122     typedef typename TL::create<resultType, par1Type, par2Type, par3Type>::value asList;
01123 };
01124 template<typename R, typename P1, typename P2, typename P3> struct FnInfo<R (*)(P1, P2, P3)>
01125 {
01126     typedef R resultType;
01127     typedef NullType objectType;
01128     typedef P1 par1Type;
01129     typedef P2 par2Type;
01130     typedef P3 par3Type;
01131     static const bool isConst=false;
01132     static const int arity=3;
01133     typedef typename TL::create<resultType, par1Type, par2Type, par3Type>::value asList;
01134 };
01135 template<typename R, typename O, typename P1, typename P2, typename P3, typename P4> struct FnInfo<R (O::*)(P1, P2, P3, P4)>
01136 {
01137     typedef R resultType;
01138     typedef O objectType;
01139     typedef P1 par1Type;
01140     typedef P2 par2Type;
01141     typedef P3 par3Type;
01142     typedef P4 par4Type;
01143     static const bool isConst=false;
01144     static const int arity=4;
01145     typedef typename TL::create<resultType, par1Type, par2Type, par3Type, par4Type>::value asList;
01146 };
01147 template<typename R, typename O, typename P1, typename P2, typename P3, typename P4> struct FnInfo<R (O::*)(P1, P2, P3, P4) const>
01148 {
01149     typedef R resultType;
01150     typedef O objectType;
01151     typedef P1 par1Type;
01152     typedef P2 par2Type;
01153     typedef P3 par3Type;
01154     typedef P4 par4Type;
01155     static const bool isConst=true;
01156     static const int arity=4;
01157     typedef typename TL::create<resultType, par1Type, par2Type, par3Type, par4Type>::value asList;
01158 };
01159 template<typename R, typename P1, typename P2, typename P3, typename P4> struct FnInfo<R (*)(P1, P2, P3, P4)>
01160 {
01161     typedef R resultType;
01162     typedef NullType objectType;
01163     typedef P1 par1Type;
01164     typedef P2 par2Type;
01165     typedef P3 par3Type;
01166     typedef P4 par4Type;
01167     static const bool isConst=false;
01168     static const int arity=4;
01169     typedef typename TL::create<resultType, par1Type, par2Type, par3Type, par4Type>::value asList;
01170 };
01171 namespace FnFromListPrivate {
01172     template<typename list, int pars> struct impl;
01173     template<typename list> struct impl<list, 0> { typedef typename TL::at<list, 0>::value (*value)(); };
01174     template<typename list> struct impl<list, 1>
01175     { typedef typename TL::at<list, 0>::value (*value)(typename TL::at<list, 1>::value); };
01176     template<typename list> struct impl<list, 2>
01177     { typedef typename TL::at<list, 0>::value (*value)(typename TL::at<list, 1>::value, typename TL::at<list, 2>::value); };
01178     template<typename list> struct impl<list, 3>
01179     { typedef typename TL::at<list, 0>::value (*value)(typename TL::at<list, 1>::value, typename TL::at<list, 2>::value, typename TL::at<list, 3>::value); };
01180     template<typename list> struct impl<list, 4>
01181     { typedef typename TL::at<list, 0>::value (*value)(typename TL::at<list, 1>::value, typename TL::at<list, 2>::value, typename TL::at<list, 3>::value, typename TL::at<list, 4>::value); };
01182 }
01190 template<typename list> struct FnFromList
01191 {
01192 public:
01193     typedef typename FnFromListPrivate::impl<list, TL::length<list>::value-1>::value value;
01194 };
01195 
01200 struct IntegralLists
01201 {
01203     typedef TL::create<unsigned char, FXushort, FXuint, unsigned long, FXulong>::value unsignedInts;
01205     typedef TL::create<signed char, FXshort, FXint, signed long, FXlong>::value signedInts;
01207     typedef TL::create<bool, char>::value otherInts;
01209     typedef TL::create<FXfloat, FXdouble>::value floats;
01210 
01212     typedef TL::append<TL::append<unsignedInts, signedInts>::value, otherInts>::value Ints;
01214     typedef TL::append<TL::append<unsignedInts, signedInts>::value, floats>::value Arithmetical;
01216     typedef TL::append<signedInts, floats>::value Signeds;
01218     typedef TL::append<Ints, floats>::value All;
01219 
01221     typedef TL::at<unsignedInts, 0>::value smallestUnsignedInt;
01223     typedef TL::at<signedInts,   0>::value smallestSignedInt;
01225     typedef TL::at<floats,       0>::value smallestFloat;
01227     typedef TL::at<unsignedInts, TL::length<unsignedInts>::value-1>::value biggestUnsignedInt;
01229     typedef TL::at<signedInts,   TL::length<signedInts>::value-1>::value biggestSignedInt;
01231     typedef TL::at<floats,       TL::length<floats>::value-1>::value biggestFloat;
01232 };
01233 
01238 template<typename type, bool minus=false> struct BiggestValue
01239 {
01240 protected:
01241     static const int UnsignedIntIdx=TL::find<IntegralLists::unsignedInts, type>::value;
01242     static const int SignedIntIdx  =TL::find<IntegralLists::signedInts, type>::value;
01243     static const int intIdx=(-1==UnsignedIntIdx) ? SignedIntIdx : UnsignedIntIdx;
01244     typedef typename TL::atC<IntegralLists::unsignedInts, intIdx>::value typeAsUnsigned;
01245     static const typeAsUnsigned maxUnsignedValue=(typeAsUnsigned)-1;
01246     static const typeAsUnsigned maxUnsignedValueL1=(typeAsUnsigned)((-1==UnsignedIntIdx) ? maxUnsignedValue<<1 : maxUnsignedValue);
01247     static const typeAsUnsigned maxSignedValue=(typeAsUnsigned)((-1==UnsignedIntIdx) ? maxUnsignedValueL1>>1 : maxUnsignedValue);
01248 public:
01249     static const type value=(type)(minus ? ~maxSignedValue : maxSignedValue);
01250 };
01255 template<typename type, bool minus=false> struct SmallestValue : public BiggestValue<type, minus>
01256 {
01257     static const type value=1;
01258 };
01259 template<typename type> struct SmallestValue<type, true> : public BiggestValue<type, true>
01260 {
01261     static const type value=(BiggestValue<type, true>::UnsignedIntIdx==-1) ? -1 : 1;
01262 };
01263 #if defined(_MSC_VER) && _MSC_VER<=1400
01264 // Sadly <=MSVC80 doesn't support static const <double|float>
01265 namespace Impl { namespace
01266 {
01267     template<typename type, bool minus> struct MSVCBiggestValue;
01268     template<typename type, bool minus> struct MSVCSmallestValue;
01269     template<> struct  MSVCBiggestValue<float, false> { static  float value; };
01270     template<> struct  MSVCBiggestValue<float, true>  { static  float value; };
01271     template<> struct  MSVCBiggestValue<double, false>{ static double value; };
01272     template<> struct  MSVCBiggestValue<double, true> { static double value; };
01273     template<> struct MSVCSmallestValue<float, false> { static  float value; };
01274     template<> struct MSVCSmallestValue<float, true>  { static  float value; };
01275     template<> struct MSVCSmallestValue<double, false>{ static double value; };
01276     template<> struct MSVCSmallestValue<double, true> { static double value; };
01277      float MSVCBiggestValue <float,  false>::value=3.402823466e+38F;
01278      float MSVCBiggestValue <float,  true>::value=-3.402823466e+38F;
01279     double MSVCBiggestValue <double, false>::value=1.7976931348623158e+308;
01280     double MSVCBiggestValue <double, true>::value=-1.7976931348623158e+308;
01281      float MSVCSmallestValue<float,  false>::value=1.175494351e-38F;
01282      float MSVCSmallestValue<float,  true>::value=-1.175494351e-38F;
01283     double MSVCSmallestValue<double, false>::value=2.2250738585072014e-308;
01284     double MSVCSmallestValue<double, true>::value=-2.2250738585072014e-308;
01285 } }
01286 template<bool minus> struct  BiggestValue<float,  minus> : public Impl::MSVCBiggestValue <float , minus> { };
01287 template<bool minus> struct  BiggestValue<double, minus> : public Impl::MSVCBiggestValue <double, minus> { };
01288 template<bool minus> struct SmallestValue<float,  minus> : public Impl::MSVCSmallestValue<float , minus> { };
01289 template<bool minus> struct SmallestValue<double, minus> : public Impl::MSVCSmallestValue<double, minus> { };
01290 #else
01291 template<> struct FXAPI BiggestValue<float, false>
01292 {
01293     static const float value;
01294 };
01295 template<> struct FXAPI BiggestValue<float, true>
01296 {
01297     static const float value;
01298 };
01299 template<> struct FXAPI BiggestValue<double, false>
01300 {
01301     static const double value;
01302 };
01303 template<> struct FXAPI BiggestValue<double, true>
01304 {
01305     static const double value;
01306 };
01307 
01308 template<> struct FXAPI SmallestValue<float, false>
01309 {
01310     static const float value;
01311 };
01312 template<> struct FXAPI SmallestValue<float, true>
01313 {
01314     static const float value;
01315 };
01316 template<> struct FXAPI SmallestValue<double, false>
01317 {
01318     static const double value;
01319 };
01320 template<> struct FXAPI SmallestValue<double, true>
01321 {
01322     static const double value;
01323 };
01324 #endif
01325 
01334 namespace ClassTraits
01335 {
01336     struct POD;
01342     template<class T1=NullType> struct combine
01343     {
01344         typedef typename TL::create<T1>::value pars;
01345         static const bool PODness=TL::find<pars, POD>::value>=0;
01346     };
01361     template<class type> struct has : public combine<> { };
01362 }
01426 namespace TraitsHelper
01427 {
01428     template<typename par> struct isVoidI { static const bool value=false; };
01429     template<> struct isVoidI<void> { static const bool value=true; };
01430     template<typename par> struct polyA : public par
01431     {
01432         char foo[64];
01433     };
01434     template<typename par> struct polyB : public par
01435     {
01436         char foo[64];
01437         virtual ~polyB() { }
01438     };
01439     template<bool isComplex, typename par> struct isPolymorphicI { static const bool value=false; };
01440     template<typename par> struct isPolymorphicI<true, par>
01441     {
01442         static const bool value=sizeof(polyA<par>)==sizeof(polyB<par>);
01443     };
01444 }
01445 template<typename type> class TraitsBasic
01446 {
01447 protected:
01448     template<typename par> struct isVoidI { static const bool value=TraitsHelper::isVoidI<par>::value; };
01449     template<typename par> struct isPtrI { static const bool value=false; };
01450     template<typename par> struct isPtrI<par *> { static const bool value=true; };
01451     template<typename par> struct isRefI { static const bool value=false; };
01452     template<typename par> struct isRefI<par &> { static const bool value=true; };
01453     template<typename par> struct isArrayI { static const bool value=false; };
01454     template<typename T, unsigned int len> struct isArrayI<T[len]> { static const bool value=true; };
01455     template<typename T, unsigned int len> struct isArrayI<T const[len]> { static const bool value=true; };
01456     template<typename T, unsigned int len> struct isArrayI<T volatile[len]> { static const bool value=true; };
01457     template<typename T, unsigned int len> struct isArrayI<T const volatile[len]> { static const bool value=true; };
01458     template<typename par> struct isConstI { static const bool value=false; };
01459     template<typename par> struct isConstI<const par> { static const bool value=true; };
01460     template<typename par> struct isVolatileI { static const bool value=false; };
01461     template<typename par> struct isVolatileI<volatile par> { static const bool value=true; };
01462     typedef FnInfo<type> fnInfo;
01463     template<bool wantConst, typename par> struct addConstI { typedef par value; };
01464     template<typename par> struct addConstI<true, par> { typedef const par value; };
01465 public:
01466     static const bool isVoid=isVoidI<type>::value;
01467     static const bool isPtr=isPtrI<type>::value;
01468     static const bool isRef=isRefI<type>::value;
01469     static const bool isPtrToCode=fnInfo::arity>=0;
01470     static const bool isMemberPtr=isPtrToCode && !sameType<typename fnInfo::objectType, NullType>::value;
01471     static const bool isFunctionPtr=isPtrToCode && sameType<typename fnInfo::objectType, NullType>::value;
01472     static const bool isValue=!isPtr && !isRef && !isPtrToCode;
01473     static const bool isIndirect=!isValue;
01474     static const bool isConst=isConstI<type>::value;
01475     static const bool isVolatile=isVolatileI<type>::value;
01476 
01477     typedef typename leastIndir<type>::value baseType;
01478     static const bool isArray=isArrayI<baseType>::value;
01479     static const bool isFloat=TL::find<IntegralLists::floats, baseType>::value>=0;
01480     static const bool isInt=TL::find<IntegralLists::Ints, baseType>::value>=0;
01481     static const bool isSigned=TL::find<IntegralLists::Signeds, baseType>::value>=0;
01482     static const bool isUnsigned=TL::find<IntegralLists::unsignedInts, baseType>::value>=0;
01483     static const bool isArithmetical=TL::find<IntegralLists::Arithmetical, baseType>::value>=0;
01484     static const bool isIntegral=TL::find<IntegralLists::All, baseType>::value>=0;
01485     static const bool isBasic=isIntegral;
01486     static const bool holdsData=!isIntegral && !isPtrToCode;
01487 
01488     static const bool isPOD=isBasic || ClassTraits::has<type>::PODness;
01489 
01490     typedef typename select<isIntegral || isIndirect, type, typename addRef<type>::value >::value asRWParam;
01491     typedef typename addConstI<!isIntegral && !isRef, type>::value asConstParam;
01492 private:
01493     typedef typename TL::create<asRWParam, asConstParam, typename addRef<asConstParam>::value>::value ROParams;
01494 public:
01495     typedef typename TL::at<ROParams, ((isValue && isBasic) || isRef) ? 0 : (isIndirect) ? 1 : 2>::value asROParam;
01496 };
01497 template<typename type> class Traits : public TraitsBasic<type>
01498 {
01499     enum TestEnum {};
01500     template<bool isCodePtr, typename par> struct isEnumSizeI { static const bool value=false; };
01501     template<typename par> struct isEnumSizeI<false, par> { static const bool value=sizeof(TestEnum)==sizeof(par); };
01502 private:
01503     static const bool int_baseTypeIsVoid=TraitsHelper::isVoidI<typename TraitsBasic<type>::baseType>::value;
01504     static const bool int_isEnumSize=isEnumSizeI<TraitsBasic<type>::isPtrToCode || int_baseTypeIsVoid, typename TraitsBasic<type>::baseType>::value;
01505     static const bool int_isConvertibleToInt=!TraitsBasic<type>::isPtrToCode && convertible<int, typename TraitsBasic<type>::baseType>::value;
01506 public:
01507     static const bool isEnum=TraitsBasic<type>::holdsData && !TraitsBasic<type>::isArray && int_isEnumSize && int_isConvertibleToInt;
01508     static const bool isPolymorphic=TraitsHelper::isPolymorphicI<TraitsBasic<type>::holdsData && !TraitsBasic<type>::isArray && !isEnum && !int_baseTypeIsVoid, typename TraitsBasic<type>::baseType>::value;
01509 };
01510 
01511 
01512 
01513 
01514 namespace FunctorHelper {
01515     template<typename parslist> struct ImplBaseBase
01516     {
01517         typedef typename TL::at<parslist, 0>::value R;
01518         typedef typename TL::at<parslist, 1>::value P1base;
01519         typedef typename TraitsBasic<P1base>::asROParam P1;
01520         typedef typename TL::at<parslist, 2>::value P2base;
01521         typedef typename TraitsBasic<P2base>::asROParam P2;
01522         typedef typename TL::at<parslist, 3>::value P3base;
01523         typedef typename TraitsBasic<P3base>::asROParam P3;
01524         typedef typename TL::at<parslist, 4>::value P4base;
01525         typedef typename TraitsBasic<P4base>::asROParam P4;
01526         virtual ~ImplBaseBase() { }
01527         virtual ImplBaseBase *copy() const=0;
01528     };
01529     template<typename parslist, int pars> struct ImplBaseOp;
01530     template<typename parslist> struct ImplBaseOp<parslist, 0> : public ImplBaseBase<parslist>
01531     {   virtual bool operator==(const ImplBaseOp &) const=0; virtual typename ImplBaseBase<parslist>::R operator()()=0; };
01532     template<typename parslist> struct ImplBaseOp<parslist, 1> : public ImplBaseBase<parslist>
01533     {   virtual bool operator==(const ImplBaseOp &) const=0; virtual typename ImplBaseBase<parslist>::R operator()(typename ImplBaseBase<parslist>::P1 p1)=0; };
01534     template<typename parslist> struct ImplBaseOp<parslist, 2> : public ImplBaseBase<parslist>
01535     {   virtual bool operator==(const ImplBaseOp &) const=0; virtual typename ImplBaseBase<parslist>::R operator()(typename ImplBaseBase<parslist>::P1 p1, typename ImplBaseBase<parslist>::P2 p2)=0; };
01536     template<typename parslist> struct ImplBaseOp<parslist, 3> : public ImplBaseBase<parslist>
01537     {   virtual bool operator==(const ImplBaseOp &) const=0; virtual typename ImplBaseBase<parslist>::R operator()(typename ImplBaseBase<parslist>::P1 p1, typename ImplBaseBase<parslist>::P2 p2, typename ImplBaseBase<parslist>::P3 p3)=0; };
01538     template<typename parslist> struct ImplBaseOp<parslist, 4> : public ImplBaseBase<parslist>
01539     {   virtual bool operator==(const ImplBaseOp &) const=0; virtual typename ImplBaseBase<parslist>::R operator()(typename ImplBaseBase<parslist>::P1 p1, typename ImplBaseBase<parslist>::P2 p2, typename ImplBaseBase<parslist>::P3 p3, typename ImplBaseBase<parslist>::P4 p4)=0; };
01540 
01541     template<typename parentfunctor, typename fn> class ImplFn : public parentfunctor::ImplBase
01542     {
01543         typedef typename parentfunctor::ImplBase::R  R;
01544         typedef typename parentfunctor::ImplBase::P1 P1;
01545         typedef typename parentfunctor::ImplBase::P2 P2;
01546         typedef typename parentfunctor::ImplBase::P3 P3;
01547         typedef typename parentfunctor::ImplBase::P4 P4;
01548         fn fnptr;
01549     public:
01550         ImplFn(fn _fnptr) : fnptr(_fnptr) { }
01551         ImplFn(const ImplFn &o) : fnptr(o.fnptr) { }
01552         ImplFn *copy() const { return new ImplFn(*this); }
01553         bool operator==(typename parentfunctor::ImplBase const &o) const { return fnptr==static_cast<const ImplFn &>(o).fnptr; }
01554         R operator()() { return fnptr(); }
01555         R operator()(P1 p1) { return fnptr(p1); }
01556         R operator()(P1 p1, P2 p2) { return fnptr(p1, p2); }
01557         R operator()(P1 p1, P2 p2, P3 p3) { return fnptr(p1, p2, p3); }
01558         R operator()(P1 p1, P2 p2, P3 p3, P4 p4) { return fnptr(p1, p2, p3, p4); }
01559     };
01560     template<typename parentfunctor, class obj, typename fn> class ImplMemFn : public parentfunctor::ImplBase
01561     {
01562         typedef typename parentfunctor::ImplBase::R  R;
01563         typedef typename parentfunctor::ImplBase::P1 P1;
01564         typedef typename parentfunctor::ImplBase::P2 P2;
01565         typedef typename parentfunctor::ImplBase::P3 P3;
01566         typedef typename parentfunctor::ImplBase::P4 P4;
01567         obj &objinst;
01568         fn fnptr;
01569     public:
01570         ImplMemFn(obj &_objinst, fn _fnptr) : objinst(_objinst), fnptr(_fnptr) { }
01571         ImplMemFn(const ImplMemFn &o) : objinst(o.objinst), fnptr(o.fnptr) { }
01572         ImplMemFn *copy() const { return new ImplMemFn(*this); }
01573         bool operator==(typename parentfunctor::ImplBase const &o) const { return &objinst==&static_cast<const ImplMemFn &>(o).objinst && fnptr==static_cast<const ImplMemFn &>(o).fnptr; }
01574         R operator()() { return (objinst.*fnptr)(); }
01575         R operator()(P1 p1) { return (objinst.*fnptr)(p1); }
01576         R operator()(P1 p1, P2 p2) { return (objinst.*fnptr)(p1, p2); }
01577         R operator()(P1 p1, P2 p2, P3 p3) { return (objinst.*fnptr)(p1, p2, p3); }
01578         R operator()(P1 p1, P2 p2, P3 p3, P4 p4) { return (objinst.*fnptr)(p1, p2, p3, p4); }
01579     };
01580 }
01581 
01605 template<typename parslist> class Functor
01606 {
01607 public: // Has to be public unfortunately so it can be inherited off
01608     typedef typename FunctorHelper::ImplBaseOp<parslist, TL::length<parslist>::value-1> ImplBase;
01609 private:
01610     ImplBase *fnimpl;
01611     typedef typename FnFromList<parslist>::value ParsListAsFnType;
01612 public:
01613     typedef parslist ParsList;
01614     typedef typename ImplBase::R  R;
01615     typedef typename ImplBase::P1 P1;
01616     typedef typename ImplBase::P2 P2;
01617     typedef typename ImplBase::P3 P3;
01618     typedef typename ImplBase::P4 P4;
01620     Functor() : fnimpl(0) { }
01622     template<typename fn> explicit Functor(fn fnptr) : fnimpl(0)
01623     { FXERRHM((fnimpl=new FunctorHelper::ImplFn<Functor, fn>(fnptr))); }
01625     template<typename obj, typename fn> Functor(obj &objinst, fn fnptr) : fnimpl(0)
01626     { FXERRHM((fnimpl=new FunctorHelper::ImplMemFn<Functor, obj, fn>(objinst, fnptr))); }
01628     template<typename obj, typename fn> Functor(obj *objinst, fn fnptr) : fnimpl(0)
01629     { FXERRHM((fnimpl=new FunctorHelper::ImplMemFn<Functor, obj, fn>(*objinst, fnptr))); }
01630     struct void_ {};
01633     Functor(void_ *fnptr) : fnimpl(0)
01634     { if(fnptr) FXERRHM((fnimpl=new FunctorHelper::ImplFn<Functor, ParsListAsFnType>((ParsListAsFnType) fnptr))); }
01636     explicit Functor(ImplBase *_fnimpl) : fnimpl(_fnimpl) { }
01637 #ifndef HAVE_CPP0XRVALUEREFS
01638 #ifdef HAVE_CONSTTEMPORARIES
01639     Functor(const Functor &other) : fnimpl(other.fnimpl)
01640     {
01641         Functor &o=const_cast<Functor &>(other);
01642 #else
01643     Functor(Functor &o) : fnimpl(o.fnimpl)
01644     {
01645 #endif
01646 #else
01647 private:
01648     Functor(const Functor &);       // disable copy constructor
01649 public:
01650     Functor(Functor &&o) : fnimpl(std::move(o.fnimpl))
01651     {
01652 #endif
01653         o.fnimpl=0;
01654     }
01655 #ifndef HAVE_CPP0XRVALUEREFS
01656     Functor &operator=(Functor &o)
01657 #else
01658     Functor &&operator=(Functor &&o)
01659 #endif
01660     {
01661         FXDELETE(fnimpl);
01662         fnimpl=o.fnimpl;
01663         o.fnimpl=0;
01664         return *this;
01665     }
01666     ~Functor() { FXDELETE(fnimpl); }
01668     Functor copy() const
01669     {
01670         ImplBase *newimpl(static_cast<ImplBase *>(fnimpl->copy()));
01671         FXERRHM(newimpl);
01672         return Functor(newimpl);
01673     }
01675     bool operator==(const Functor &o) const { return *fnimpl==*o.fnimpl; }
01677     bool operator!=(const Functor &o) const { return !(*fnimpl==*o.fnimpl); }
01678     // Workaround to implement if(sp)
01679 private:
01680     struct Tester
01681     {
01682     private:
01683         void operator delete(void *);
01684     };
01685 public:
01686     operator Tester *() const
01687     {
01688         if(!*this) return 0;
01689         static Tester t;
01690         return &t;
01691     }
01692     // For if(!sp) 
01693     bool operator!() const { return !fnimpl; }
01695     R operator()() { return (*fnimpl)(); }
01697     R operator()(P1 p1) { return (*fnimpl)(p1); }
01699     R operator()(P1 p1, P2 p2) { return (*fnimpl)(p1, p2); }
01701     R operator()(P1 p1, P2 p2, P3 p3) { return (*fnimpl)(p1, p2, p3); }
01703     R operator()(P1 p1, P2 p2, P3 p3, P4 p4) { return (*fnimpl)(p1, p2, p3, p4); }
01704 };
01710 class BoundFunctorV
01711 {
01712     virtual void callV()=0;
01713 protected:
01714     BoundFunctorV() {}
01715     BoundFunctorV(const BoundFunctorV &) {}
01716     BoundFunctorV &operator=(const BoundFunctorV &) { return *this; }
01717 public:
01718     virtual ~BoundFunctorV() { }
01720     void operator()() { callV(); }
01721 };
01722 
01786 template<typename parslist> class BoundFunctor : public BoundFunctorV
01787 {
01788     typedef typename TL::at<parslist, 0>::value R;
01789     typedef typename TraitsBasic<typename TL::at<parslist, 1>::value>::asROParam P1;
01790     typedef typename TraitsBasic<typename TL::at<parslist, 2>::value>::asROParam P2;
01791     typedef typename TraitsBasic<typename TL::at<parslist, 3>::value>::asROParam P3;
01792     typedef typename TraitsBasic<typename TL::at<parslist, 4>::value>::asROParam P4;
01793     Functor<parslist> myfunctor;
01794     typedef typename parslist::next realparslist;
01795     TL::instantiateH<realparslist> parvals;
01796     // Stupid GCC won't permit explicit specialisation inside a class
01797     // and we can't partially specialise functions :(
01798     R call(IntToType<0>) { return myfunctor(); }
01799     R call(IntToType<1>) { return myfunctor(TL::instance<0>(parvals).value); }
01800     R call(IntToType<2>) { return myfunctor(TL::instance<0>(parvals).value, TL::instance<1>(parvals).value); }
01801     R call(IntToType<3>) { return myfunctor(TL::instance<0>(parvals).value, TL::instance<1>(parvals).value, TL::instance<2>(parvals).value); }
01802     R call(IntToType<4>) { return myfunctor(TL::instance<0>(parvals).value, TL::instance<1>(parvals).value, TL::instance<2>(parvals).value, TL::instance<3>(parvals).value); }
01803 public:
01805     template<typename fn> BoundFunctor(fn fnptr, TL::instantiateH<realparslist> &_parvals)
01806         : myfunctor(fnptr), parvals(_parvals), BoundFunctorV() { }
01808     template<typename obj, typename fn> BoundFunctor(obj &objinst, fn fnptr, TL::instantiateH<realparslist> &_parvals)
01809         : myfunctor(objinst, fnptr), parvals(_parvals), BoundFunctorV() { }
01811 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER<=800
01812     // Avoid usage of templated copy constructor (bug in ICC)
01813     BoundFunctor(const Functor<parslist> &_functor)
01814     {
01815         Functor<parslist> functor=_functor.copy();
01816         myfunctor=functor;
01817 #else
01818     BoundFunctor(const Functor<parslist> &_functor) : myfunctor(_functor.copy())
01819     {
01820 #endif
01821     }
01823 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER<=800
01824     // Avoid usage of templated copy constructor (bug in ICC)
01825     BoundFunctor(const Functor<parslist> &_functor, P1 p1)
01826     {
01827         Functor<parslist> functor=_functor.copy();
01828         myfunctor=functor;
01829 #else
01830     BoundFunctor(const Functor<parslist> &_functor, P1 p1) : myfunctor(_functor.copy())
01831     {
01832 #endif
01833         TL::instance<0>(parvals).value=p1;
01834     }
01836 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER<=800
01837     // Avoid usage of templated copy constructor (bug in ICC)
01838     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2)
01839     {
01840         Functor<parslist> functor=_functor.copy();
01841         myfunctor=functor;
01842 #else
01843     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2) : myfunctor(_functor.copy())
01844     {
01845 #endif
01846         TL::instance<0>(parvals).value=p1;
01847         TL::instance<1>(parvals).value=p2;
01848     }
01850 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER<=800
01851     // Avoid usage of templated copy constructor (bug in ICC)
01852     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2, P3 p3)
01853     {
01854         Functor<parslist> functor=_functor.copy();
01855         myfunctor=functor;
01856 #else
01857     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2, P3 p3) : myfunctor(_functor.copy())
01858     {
01859 #endif
01860         TL::instance<0>(parvals).value=p1;
01861         TL::instance<1>(parvals).value=p2;
01862         TL::instance<2>(parvals).value=p3;
01863     }
01865 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER<=800
01866     // Avoid usage of templated copy constructor (bug in ICC)
01867     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2, P3 p3, P4 p4)
01868     {
01869         Functor<parslist> functor=_functor.copy();
01870         myfunctor=functor;
01871 #else
01872     BoundFunctor(const Functor<parslist> &_functor, P1 p1, P2 p2, P3 p3, P4 p4) : myfunctor(_functor.copy())
01873     {
01874 #endif
01875         TL::instance<0>(parvals).value=p1;
01876         TL::instance<1>(parvals).value=p2;
01877         TL::instance<2>(parvals).value=p3;
01878         TL::instance<3>(parvals).value=p4;
01879     }
01880     BoundFunctor(const BoundFunctor &o) : myfunctor(o.myfunctor.copy()), parvals(o.parvals), BoundFunctorV(o) { }
01881     BoundFunctor &operator=(const BoundFunctor &o)
01882     {
01883         myfunctor=o.myfunctor.copy();
01884         parvals=o.parvals;
01885         return *this;
01886     }
01888     Functor<parslist> &functor() { return myfunctor; }
01890     TL::instantiateH<realparslist> &parameters() { return parvals; }
01892     R operator()() { return call(IntToType<TL::length<parslist>::value-1>()); }
01893 private:
01894     void callV() { (*this)(); }
01895 
01896     // MSVC compiles wrong code if these are defined :(
01897     //template<typename F> friend BoundFunctor<typename F::ParsList> BindFunctor(F &functor);
01898     //template<typename F> friend BoundFunctor<typename F::ParsList> *BindFunctorN(F &functor);
01899     //template<typename fn> friend BoundFunctor<typename FnInfo<fn>::asList> BindFunc(fn fnptr);
01900     //template<typename fn> friend BoundFunctor<typename FnInfo<fn>::asList> *BindFuncN(fn fnptr);
01901     //template<typename obj, typename fn> friend BoundFunctor<typename FnInfo<fn>::asList> BindObj(obj &objinst, fn fnptr);
01902     //template<typename obj, typename fn> friend BoundFunctor<typename FnInfo<fn>::asList> *BindObjN(obj &objinst, fn fnptr);
01903 };
01904 #ifdef DOXYGEN_SHOULD_SKIP_THIS
01905 
01908 BoundFunctor BindFunctor(FX::Generic::Functor &functor [, par1 [, par2 ...]]);
01912 BoundFunctor *BindFunctorN(FX::Generic::Functor &functor [, par1 [, par2 ...]]);
01913 #else
01914 template<typename F> BoundFunctor<typename F::ParsList>
01915     BindFunctor(F &functor)
01916 {
01917     return BoundFunctor<typename F::ParsList>(functor);
01918 }
01919 template<typename F> BoundFunctor<typename F::ParsList> *
01920     BindFunctorN(F &functor)
01921 {
01922     return new BoundFunctor<typename F::ParsList>(functor);
01923 }
01924 template<typename F> BoundFunctor<typename F::ParsList>
01925     BindFunctor(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1)
01926 {
01927     return BoundFunctor<typename F::ParsList>(functor, p1);
01928 }
01929 template<typename F> BoundFunctor<typename F::ParsList> *
01930     BindFunctorN(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1)
01931 {
01932     return new BoundFunctor<typename F::ParsList>(functor, p1);
01933 }
01934 template<typename F> BoundFunctor<typename F::ParsList>
01935     BindFunctor(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01936     typename TraitsBasic<typename F::P2>::asROParam p2)
01937 {
01938     return BoundFunctor<typename F::ParsList>(functor, p1, p2);
01939 }
01940 template<typename F> BoundFunctor<typename F::ParsList> *
01941     BindFunctorN(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01942     typename TraitsBasic<typename F::P2>::asROParam p2)
01943 {
01944     return new BoundFunctor<typename F::ParsList>(functor, p1, p2);
01945 }
01946 template<typename F> BoundFunctor<typename F::ParsList>
01947     BindFunctor(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01948     typename TraitsBasic<typename F::P2>::asROParam p2, typename TraitsBasic<typename F::P3>::asROParam p3)
01949 {
01950     return BoundFunctor<typename F::ParsList>(functor, p1, p2, p3);
01951 }
01952 template<typename F> BoundFunctor<typename F::ParsList> *
01953     BindFunctorN(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01954     typename TraitsBasic<typename F::P2>::asROParam p2, typename TraitsBasic<typename F::P3>::asROParam p3)
01955 {
01956     return new BoundFunctor<typename F::ParsList>(functor, p1, p2, p3);
01957 }
01958 template<typename F> BoundFunctor<typename F::ParsList>
01959     BindFunctor(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01960     typename TraitsBasic<typename F::P2>::asROParam p2, typename TraitsBasic<typename F::P3>::asROParam p3,
01961     typename TraitsBasic<typename F::P4>::asROParam p4)
01962 {
01963     return BoundFunctor<typename F::ParsList>(functor, p1, p2, p3, p4);
01964 }
01965 template<typename F> BoundFunctor<typename F::ParsList> *
01966     BindFunctorN(F &functor, typename TraitsBasic<typename F::P1>::asROParam p1,
01967     typename TraitsBasic<typename F::P2>::asROParam p2, typename TraitsBasic<typename F::P3>::asROParam p3,
01968     typename TraitsBasic<typename F::P4>::asROParam p4)
01969 {
01970     return new BoundFunctor<typename F::ParsList>(functor, p1, p2, p3, p4);
01971 }
01972 #endif
01973 #ifdef DOXYGEN_SHOULD_SKIP_THIS
01974 
01977 BoundFunctor<> BindFunc(functptr [, par1 [, par2 ...]]);
01981 BoundFunctor<> BindFuncN(functptr [, par1 [, par2 ...]]);
01985 BoundFunctor<> BindObj(obj &, memfunctptr [, par1 [, par2 ...]]);
01989 BoundFunctor<> BindObjN(obj &, memfunctptr [, par1 [, par2 ...]]);
01990 #else
01991 namespace Bind {
01992     template<int pars, typename fn> struct Impl
01993     {
01994         typedef typename FnInfo<fn>::asList fnspec;
01995         TL::instantiateH<typename fnspec::next> parvals;
01996         void checkParms()
01997         {
01998             FXSTATIC_ASSERT(TL::length<fnspec>::value-1==pars, Function_Spec_Not_Equal_To_Parameters_Specified);
01999         }
02000         Impl() {}
02001         template<typename P1> Impl(P1 p1)
02002         {
02003             TL::instance<0>(parvals).value=p1;
02004         }
02005         template<typename P1, typename P2> Impl(P1 p1, P2 p2)
02006         {
02007             TL::instance<0>(parvals).value=p1;
02008             TL::instance<1>(parvals).value=p2;
02009         }
02010         template<typename P1, typename P2, typename P3> Impl(P1 p1, P2 p2, P3 p3)
02011         {
02012             TL::instance<0>(parvals).value=p1;
02013             TL::instance<1>(parvals).value=p2;
02014             TL::instance<2>(parvals).value=p3;
02015         }
02016         template<typename P1, typename P2, typename P3, typename P4> Impl(P1 p1, P2 p2, P3 p3, P4 p4)
02017         {
02018             TL::instance<0>(parvals).value=p1;
02019             TL::instance<1>(parvals).value=p2;
02020             TL::instance<2>(parvals).value=p3;
02021             TL::instance<3>(parvals).value=p4;
02022         }
02023     };
02024 }
02025 template<typename fn> BoundFunctor<typename FnInfo<fn>::asList>
02026     BindFunc(fn fnptr)
02027 {
02028     typedef typename Bind::Impl<0, fn> Impl;
02029     Impl impl;
02030     return BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02031 }
02032 template<typename fn> BoundFunctor<typename FnInfo<fn>::asList> *
02033     BindFuncN(fn fnptr)
02034 {
02035     typedef typename Bind::Impl<0, fn> Impl;
02036     Impl impl;
02037     return new BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02038 }
02039 template<typename fn, typename P1> BoundFunctor<typename FnInfo<fn>::asList>
02040     BindFunc(fn fnptr, P1 p1)
02041 {
02042     typedef typename Bind::Impl<1, fn> Impl;
02043     Impl impl(p1);
02044     return BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02045 }
02046 template<typename fn, typename P1> BoundFunctor<typename FnInfo<fn>::asList> *
02047     BindFuncN(fn fnptr, P1 p1)
02048 {
02049     typedef typename Bind::Impl<1, fn> Impl;
02050     Impl impl(p1);
02051     return new BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02052 }
02053 template<typename fn, typename P1, typename P2> BoundFunctor<typename FnInfo<fn>::asList>
02054     BindFunc(fn fnptr, P1 p1, P2 p2)
02055 {
02056     typedef typename Bind::Impl<2, fn> Impl;
02057     Impl impl(p1, p2);
02058     return BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02059 }
02060 template<typename fn, typename P1, typename P2> BoundFunctor<typename FnInfo<fn>::asList> *
02061     BindFuncN(fn fnptr, P1 p1, P2 p2)
02062 {
02063     typedef typename Bind::Impl<2, fn> Impl;
02064     Impl impl(p1, p2);
02065     return new BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02066 }
02067 template<typename fn, typename P1, typename P2, typename P3> BoundFunctor<typename FnInfo<fn>::asList>
02068     BindFunc(fn fnptr, P1 p1, P2 p2, P3 p3)
02069 {
02070     typedef typename Bind::Impl<3, fn> Impl;
02071     Impl impl(p1, p2, p3);
02072     return BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02073 }
02074 template<typename fn, typename P1, typename P2, typename P3> BoundFunctor<typename FnInfo<fn>::asList> *
02075     BindFuncN(fn fnptr, P1 p1, P2 p2, P3 p3)
02076 {
02077     typedef typename Bind::Impl<3, fn> Impl;
02078     Impl impl(p1, p2, p3);
02079     return new BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02080 }
02081 template<typename fn, typename P1, typename P2, typename P3, typename P4> BoundFunctor<typename FnInfo<fn>::asList>
02082     BindFunc(fn fnptr, P1 p1, P2 p2, P3 p3, P4 p4)
02083 {
02084     typedef typename Bind::Impl<4, fn> Impl;
02085     Impl impl(p1, p2, p3, p4);
02086     return BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02087 }
02088 template<typename fn, typename P1, typename P2, typename P3, typename P4> BoundFunctor<typename FnInfo<fn>::asList> *
02089     BindFuncN(fn fnptr, P1 p1, P2 p2, P3 p3, P4 p4)
02090 {
02091     typedef typename Bind::Impl<3, fn> Impl;
02092     Impl impl(p1, p2, p3, p4);
02093     return new BoundFunctor<typename Impl::fnspec>(fnptr, impl.parvals);
02094 }
02095 template<typename obj, typename fn> BoundFunctor<typename FnInfo<fn>::asList>
02096     BindObj(obj &objinst, fn fnptr)
02097 {
02098     typedef typename Bind::Impl<0, fn> Impl;
02099     Impl impl;
02100     return BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02101 }
02102 template<typename obj, typename fn> BoundFunctor<typename FnInfo<fn>::asList> *
02103     BindObjN(obj &objinst, fn fnptr)
02104 {
02105     typedef typename Bind::Impl<0, fn> Impl;
02106     Impl impl;
02107     return new BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02108 }
02109 template<typename obj, typename fn, typename P1> BoundFunctor<typename FnInfo<fn>::asList>
02110     BindObj(obj &objinst, fn fnptr, P1 p1)
02111 {
02112     typedef typename Bind::Impl<1, fn> Impl;
02113     Impl impl(p1);
02114     return BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02115 }
02116 template<typename obj, typename fn, typename P1> BoundFunctor<typename FnInfo<fn>::asList> *
02117     BindObjN(obj &objinst, fn fnptr, P1 p1)
02118 {
02119     typedef typename Bind::Impl<1, fn> Impl;
02120     Impl impl(p1);
02121     return new BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02122 }
02123 template<typename obj, typename fn, typename P1, typename P2> BoundFunctor<typename FnInfo<fn>::asList>
02124     BindObj(obj &objinst, fn fnptr, P1 p1, P2 p2)
02125 {
02126     typedef typename Bind::Impl<2, fn> Impl;
02127     Impl impl(p1, p2);
02128     return BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02129 }
02130 template<typename obj, typename fn, typename P1, typename P2> BoundFunctor<typename FnInfo<fn>::asList> *
02131     BindObjN(obj &objinst, fn fnptr, P1 p1, P2 p2)
02132 {
02133     typedef typename Bind::Impl<2, fn> Impl;
02134     Impl impl(p1, p2);
02135     return new BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02136 }
02137 template<typename obj, typename fn, typename P1, typename P2, typename P3> BoundFunctor<typename FnInfo<fn>::asList>
02138     BindObj(obj &objinst, fn fnptr, P1 p1, P2 p2, P3 p3)
02139 {
02140     typedef typename Bind::Impl<3, fn> Impl;
02141     Impl impl(p1, p2, p3);
02142     return BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02143 }
02144 template<typename obj, typename fn, typename P1, typename P2, typename P3> BoundFunctor<typename FnInfo<fn>::asList> *
02145     BindObjN(obj &objinst, fn fnptr, P1 p1, P2 p2, P3 p3)
02146 {
02147     typedef typename Bind::Impl<3, fn> Impl;
02148     Impl impl(p1, p2, p3);
02149     return new BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02150 }
02151 template<typename obj, typename fn, typename P1, typename P2, typename P3, typename P4> BoundFunctor<typename FnInfo<fn>::asList>
02152     BindObj(obj &objinst, fn fnptr, P1 p1, P2 p2, P3 p3, P4 p4)
02153 {
02154     typedef typename Bind::Impl<4, fn> Impl;
02155     Impl impl(p1, p2, p3, p4);
02156     return BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02157 }
02158 template<typename obj, typename fn, typename P1, typename P2, typename P3, typename P4> BoundFunctor<typename FnInfo<fn>::asList> *
02159     BindObjN(obj &objinst, fn fnptr, P1 p1, P2 p2, P3 p3, P4 p4)
02160 {
02161     typedef typename Bind::Impl<4, fn> Impl;
02162     Impl impl(p1, p2, p3, p4);
02163     return new BoundFunctor<typename Impl::fnspec>(objinst, fnptr, impl.parvals);
02164 }
02165 #endif
02166 
02167 namespace TL
02168 {
02169     namespace dynamicAtHelper
02170     {
02171         template<typename fnspeclist, typename typelist, template<class> class instance> struct Impl
02172         {
02173             typedef typename FnFromList<fnspeclist>::value fnspec;
02174             static fnspec getArray(FXuint idx)
02175             {
02176                 FXSTATIC_ASSERT(length<typelist>::value<=16, DynamicAt_Maximum_Exceeded);
02177                 typedef instance<NullType> nullinst;
02178                 if(idx>=length<typelist>::value)
02179                     return &nullinst::Do;
02180                 typedef typename apply<typelist, instance>::value instancedtypelist;
02181                 typedef typename replicate<16-length<typelist>::value, instance<NullType> >::value instancedtypelistend;
02182                 typedef typename append<instancedtypelist, instancedtypelistend>::value atypelist;
02183 
02184                 static const fnspec mytable[16]={
02185                     &at<atypelist, 0>::value::Do,           &at<atypelist, 1>::value::Do,
02186                     &at<atypelist, 2>::value::Do,           &at<atypelist, 3>::value::Do,
02187                     &at<atypelist, 4>::value::Do,           &at<atypelist, 5>::value::Do,
02188                     &at<atypelist, 6>::value::Do,           &at<atypelist, 7>::value::Do,
02189                     &at<atypelist, 8>::value::Do,           &at<atypelist, 9>::value::Do,
02190                     &at<atypelist, 10>::value::Do,          &at<atypelist, 11>::value::Do,
02191                     &at<atypelist, 12>::value::Do,          &at<atypelist, 13>::value::Do,
02192                     &at<atypelist, 14>::value::Do,          &at<atypelist, 15>::value::Do
02193                     };
02194                 return mytable[idx];
02195             }
02196         };
02197     }
02226     template<typename typelist, template<class> class instance> struct dynamicAt
02227     {
02228         static const FXuint MaxEntries=16;          
02229         static const FXuint DisableMagicIdx=1<<28;  
02230 
02231         dynamicAt(FXuint idx)
02232         {
02233             typedef typename create<void>::value parslist;
02234             if(DisableMagicIdx!=idx)
02235                 dynamicAtHelper::Impl<parslist, typelist, instance>::getArray(idx)();
02236         }
02238         template<typename P1> dynamicAt(FXuint idx, P1 p1)
02239         {
02240             typedef typename create<void, P1>::value parslist;
02241             if(DisableMagicIdx!=idx)
02242                 dynamicAtHelper::Impl<parslist, typelist, instance>::getArray(idx)(p1);
02243         }
02245         template<typename P1, typename P2> dynamicAt(FXuint idx, P1 p1, P2 p2)
02246         {
02247             typedef typename create<void, P1, P2>::value parslist;
02248             if(DisableMagicIdx!=idx)
02249                 dynamicAtHelper::Impl<parslist, typelist, instance>::getArray(idx)(p1,p2);
02250         }
02252         template<typename P1, typename P2, typename P3> dynamicAt(FXuint idx, P1 p1, P2 p2, P3 p3)
02253         {
02254             typedef typename create<void, P1, P2, P3>::value parslist;
02255             if(DisableMagicIdx!=idx)
02256                 dynamicAtHelper::Impl<parslist, typelist, instance>::getArray(idx)(p1,p2,p3);
02257         }
02259         template<typename P1, typename P2, typename P3, typename P4> dynamicAt(FXuint idx, P1 p1, P2 p2, P3 p3, P4 p4)
02260         {
02261             typedef typename create<void, P1, P2, P3, P4>::value parslist;
02262             if(DisableMagicIdx!=idx)
02263                 dynamicAtHelper::Impl<parslist, typelist, instance>::getArray(idx)(p1,p2,p3,p4);
02264         }
02265 
02266     };
02267 }
02268 
02285 template<int len> struct MapBools
02286 {
02287     FXSTATIC_ASSERT2(len<=sizeof(FXulong)*8, ERROR_Too_Many_Bools_To_Fit_Into_Integral_Type);
02288     typedef typename Generic::select<(len>sizeof(FXuchar)*8),
02289                 typename Generic::select<(len>sizeof(FXushort)*8),
02290                     typename Generic::select<(len>sizeof(FXuint)*8),
02291                         FXulong,
02292                         FXuint>::value,
02293                     FXushort>::value,
02294                 FXuchar>::value
02295             holdtype;
02296     bool *base;
02297     MapBools(const bool *_base) throw() : base(const_cast<bool *>(_base)) { }
02298 
02299     // Avoid variable bit shifts as they're slow on x86
02300     friend inline FXStream &operator<<(FXStream &s, const MapBools<len> i) throw()
02301     {
02302         holdtype val=0;
02303         for(int n=len-1; n>=0; n--)
02304         {
02305             val=(val<<1)|((FXuchar)i.base[n]);
02306         }
02307         s << val;
02308         return s;
02309     }
02310     friend inline FXStream &operator>>(FXStream &s, MapBools<len> i) throw()
02311     {
02312         holdtype val; s >> val;
02313         for(int n=0; n<len; n++)
02314         {
02315             i.base[n]=(bool)(val & 1); val>>=1;
02316         }
02317         return s;
02318     }
02319 };
02320 
02343 template<class obj=NullType, typename doaddr=NullType, typename undoaddr=NullType> class DoUndo
02344 {
02345     bool done;
02346     obj *instance;
02347     doaddr doa;
02348     undoaddr undoa;
02349 public:
02351     DoUndo(obj *_instance, doaddr _doa, undoaddr _undoa) : done(false), instance(_instance), doa(_doa), undoa(_undoa) { redo(); }
02353     ~DoUndo() { undo(); }
02355     void undo()
02356     {
02357         if(done)
02358         {
02359             (*instance.*undoa)();
02360             done=false;
02361         }
02362     }
02364     void redo()
02365     {
02366         if(!done)
02367         {
02368             (*instance.*doa)();
02369             done=true;
02370         }
02371     }
02372 };
02373 template<typename doaddr, typename undoaddr> class DoUndo<void, doaddr, undoaddr>
02374 {
02375     bool done;
02376     doaddr doa;
02377     undoaddr undoa;
02378 public:
02379     DoUndo(doaddr _doa, undoaddr _undoa) : done(false), doa(_doa), undoa(_undoa) { redo(); }
02380     ~DoUndo() { undo(); }
02381     void undo()
02382     {
02383         if(done)
02384         {
02385             (undoa)();
02386             done=false;
02387         }
02388     }
02389     void redo()
02390     {
02391         if(!done)
02392         {
02393             (doa)();
02394             done=true;
02395         }
02396     }
02397 };
02398 template<> class DoUndo<NullType, NullType, NullType>
02399 {
02400     bool done;
02401     BoundFunctorV *do_, *undo_;
02402 public:
02403     DoUndo(BoundFunctorV *_do_, BoundFunctorV *_undo_)
02404         : done(false), do_(_do_), undo_(_undo_) { redo(); }
02405     ~DoUndo() { undo(); FXDELETE(do_); FXDELETE(undo_); }
02406     void undo()
02407     {
02408         if(done)
02409         {
02410             (*undo_)();
02411             done=false;
02412         }
02413     }
02414     void redo()
02415     {
02416         if(!done)
02417         {
02418             (*do_)();
02419             done=true;
02420         }
02421     }
02422 };
02423 
02424 } // namespace
02425 
02438 #define FXAutoPtr FX::Generic::ptr  // TODO: FIXME when templated typedefs get implemented
02439 
02459 #if defined(WIN32) && defined(UNICODE)
02460 template<size_t fastlen=2048> class FXUnicodify
02461 {
02462     bool myIsPath;
02463     FXnchar stkbuff[fastlen], *mybuffer;
02464     FXAutoPtr<FXnchar> membuff;
02465     FXint bufflen;
02466     void doConv(const FXString &_str)
02467     {
02468         FXString str(_str);
02469         if(myIsPath)
02470         {
02471             str=FXPath::absolute(str);
02472             str.prepend("\\\\?\\");
02473             // Also all \ must be /
02474             str.substitute('/', '\\');
02475         }
02476         FXint strlen=str.length()+1;    // Outputted buffer will always be shorter than this
02477         if(strlen>sizeof(stkbuff))
02478             FXERRHM(membuff=mybuffer=new FXnchar[strlen]);
02479         else mybuffer=stkbuff;
02480         bufflen=utf2ncs(mybuffer, str.text(), strlen)*sizeof(FXnchar);
02481     }
02482 public:
02484     FXUnicodify(bool isPath=false) : myIsPath(isPath), mybuffer(0), bufflen(0) { }
02486     FXUnicodify(const FXString &str, bool isPath=false) : myIsPath(isPath), mybuffer(0), bufflen(0) { doConv(str); }
02488     const FXnchar *buffer() const throw() { return mybuffer; }
02490     const FXnchar *buffer(const FXString &str) { if(!mybuffer) doConv(str); return mybuffer; }
02492     FXint length() const throw() { return bufflen; }
02494     FXint length(const FXString &str) { if(!mybuffer) doConv(str); return bufflen; }
02495 };
02496 #else
02497 template<size_t fastlen=2048> class FXUnicodify
02498 {
02499     const FXchar *mybuffer;
02500     FXint bufflen;
02501 public:
02502     FXUnicodify(bool isPath=false) : mybuffer(0) { }
02503     FXUnicodify(const FXString &str, bool isPath=false) : mybuffer(str.text()), bufflen(str.length()) { }
02504     const FXchar *buffer() const throw() { return mybuffer; }
02505     const FXchar *buffer(const FXString &str) const throw() { return str.text(); }
02506     FXint length() const throw() { return bufflen; }
02507     FXint length(const FXString &str) const throw() { return str.length(); }
02508 };
02509 #endif
02510 
02511 } // namespace
02512 
02513 #endif

(C) 2002-2009 Niall Douglas. Some parts (C) to assorted authors.
Generated on Fri Nov 20 18:31:21 2009 for TnFOX by doxygen v1.4.7