// // Copyright (c) 2003 by Stephen C. Dewhurst // Permission to use, copy, modify, distribute and sell this software for any purpose is // hereby granted without fee, provided that the above copyright notice appears in all copies // and that both that copyright notice and this permission notice appear in supporting documentation. // The author makes no representations about the suitability of this software for any purpose. // It is provided "as is" without express or implied warranty. // #ifndef DISMANTLE_H #define DISMANTLE_H // // This is a quick and experimental version of a template metaprogramming // facility for compile time type manipulation. It is described in // Semantics Consulting's "Once, Weakly" feature of 23 February 2003, at // http://www.semantics.org/once_weakly.html. // // Basically, we dismantle a type into its constituent parts. We then have // the opportunity to examine its parts, change them, remove some, add some // new pieces, perform regular-expression-like matching and substitution, etc. // Finally, we can regenerate a "regular" type from the (potentially) modified // dismantled type. // // From the web posting: "In effect, we now have two equivalent, but structurally // distinct, versions of the same type. The normal version is optimized for use // in a traditional fashion: accessing its operations, causing code to be generated // that will execute at runtime, etc. The dismantled version is optimized for // compile time analysis and manipulation. Therefore, we now have the ability to // move an arbitrary type among different representations according to how we want // to use it. The invertibility of the representations assures us that either // representation will contain all the information present in the other." // // In this preliminary version, the facilities for manipulating the dismantled // type are very primitive. Bear with me... //------------------------------ // If your compiler has trouble translating some of the code below, // try recompiling with OMIT_PROBLEMATIC defined to get a limited // version of the facility. //#define OMIT_PROBLEMATIC //------------------------------ // WHAT'S HERE? // // Dismantle a type into its constituent parts. template struct Dis; // Regenerate a dismantled type. template struct Regen; // Substitute dismantled type S for any node satisfying Pred // in dismantled type T // ...for the first n appearances in T. template class Pred, class S> struct SubstN; // ...for the first appearance in T. template class Pred, class S> struct Subst; // ...for all appearances in T. template class Pred, class S> struct SubstAll; // Substitute the result of applying applicator Apply to the // current node for any node satisfying Pred in dismantled type T // ...for the first N appearances in T. template class Pred, template class Apply> struct SubstAN; //...for the first appearance in T. template class Pred, template class Apply> struct SubstA; //...for all appearances in T. template class Pred, template class Apply> struct SubstAAll; //------------------------------ // // Some utilities. // template struct IsSame { enum { r = false }; }; template struct IsSame { enum { r = true }; }; template struct Select { typedef A R; }; template struct Select { typedef B R; }; //------------------------------ // // A very simple typelist. The head is a type, // the tail is a typelist. A NullTList is a typelist. // template struct TList { typedef T Head; typedef U Tail; }; typedef struct {} NullTList; template // Alexandrescu's append struct Append; template <> struct Append { typedef NullTList R; }; template struct Append { typedef TList R; }; template struct Append< NullTList,TList > { typedef TList R; }; template struct Append,T> { typedef TList::R> R; }; //------------------------------- // // Types that represent type qualifiers and type modifiers in // the dismantled version of a type. // struct Const {}; struct Volatile {}; struct Ref {}; struct Ptr {}; template struct Ary { enum { bound = b }; }; template struct Pcm { typedef typename Dis::R Class; }; // Function modifiers (member and non-member) modify the return type. // Therefore, only the arguments are available within these modifier types. struct Fun0 {}; template struct Fun1 { typedef typename Dis::R Arg; }; template struct Fun2 { typedef typename Dis::R Arg1; typedef typename Dis::R Arg2; }; template struct MFun0 { typedef typename Dis::R Class; }; template struct MFun1 { typedef typename Dis::R Class; typedef typename Dis::R Arg; }; template struct MFun2 { typedef typename Dis::R Class; typedef typename Dis::R Arg1; typedef typename Dis::R Arg2; }; template struct CMFun0 { typedef typename Dis::R Class; }; template struct CMFun1 { typedef typename Dis::R Class; typedef typename Dis::R Arg; }; template struct CMFun2 { typedef typename Dis::R Class; typedef typename Dis::R Arg1; typedef typename Dis::R Arg2; }; //------------------------------- // TYPE DISMANTLING // // The primary template is the catch-all for any type // that is not more specifically specialized. // See specialized types below. // template struct Dis { typedef TList R; }; template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; template struct Dis< T *const> { typedef TList::R> R; }; template struct Dis< T *volatile> { typedef TList::R> R; }; template struct Dis< T *const volatile> { typedef TList::R> R; }; template struct Dis { typedef TList< Ary,typename Dis::R > R; }; template struct Dis { typedef TList,typename Dis::R> R; }; #ifndef OMIT_PROBLEMATIC template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList::R> R; }; #endif template struct Dis { typedef TList::R> R; }; template struct Dis { typedef TList,typename Dis::R> R; }; template struct Dis { typedef TList,typename Dis::R> R; }; template struct Dis { typedef TList,typename Dis::R> R; }; template struct Dis { typedef TList,typename Dis::R> R; }; template struct Dis { typedef TList,typename Dis::R> R; }; template struct Dis { typedef TList< Const,TList,typename Dis::R> > R; }; template struct Dis { typedef TList< Const, TList,typename Dis::R> > R; }; template struct Dis { typedef TList< Const, TList,typename Dis::R> > R; }; //------------------------------ // REGENERATING A DISMANTLED TYPE // template struct Regen; template struct Regen< TList > { typedef T R; }; template struct Regen< TList > { typedef const typename Regen::R R; }; template struct Regen< TList > { typedef volatile typename Regen::R R; }; template struct Regen< TList > { typedef typename Regen::R &R; }; template struct Regen< TList > { typedef typename Regen::R *R; }; template struct Regen< TList,T> > { typedef typename Regen::R R[b]; }; template struct Regen< TList,T> > { typedef typename Regen::R C::*R; }; template struct Regen< TList > { typedef typename Regen::R R(); }; template struct Regen< TList,T> > { typedef typename Regen::R R( A ); }; template struct Regen< TList,T> > { typedef typename Regen::R R( A1, A2 ); }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)(); }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)( A ); }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)( A1, A2 ); }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)() const; }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)( A ) const; }; template struct Regen< TList,T> > { typedef typename Regen::R (C::*R)( A1, A2 ) const; }; //------------------------------ // SUBSTITUTION // // Note that, because modifiers and qualifiers are represented as // types in the dismantled representation, type substitution can // be used to modify these aspects of the type as well. (For instance, // you can substitute Ptr for Ref in a dismantled type to change that // modifier in the regenerated type.) //------------------------------- // Subst applies a predicate to each node. If true, then the node is // replaced by S, which should be a Dis'ed type. template class Pred, class S> struct SubstN { typedef typename Select::r, typename Append::R>::R, TList::R> >::R R; }; template class Pred, class S> struct SubstN { typedef NullTList R; }; template class Pred, class S> struct SubstN<0,T,Pred,S> { typedef T R; }; template