HierarchyGenerators.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Wesley Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_HIERARCHYGENERATORS_INC_
00016 #define LOKI_HIERARCHYGENERATORS_INC_
00017 
00018 // $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $
00019 
00020 
00021 #include "Typelist.h"
00022 #include "TypeTraits.h"
00023 #include "EmptyType.h"
00024 
00025 namespace Loki
00026 {
00027 #if defined(_MSC_VER) && _MSC_VER >= 1300
00028 #pragma warning( push ) 
00029  // 'class1' : base-class 'class2' is already a base-class of 'class3'
00030 #pragma warning( disable : 4584 )
00031 #endif // _MSC_VER
00032 
00034 // class template GenScatterHierarchy
00035 // Generates a scattered hierarchy starting from a typelist and a template
00036 // Invocation (TList is a typelist, Unit is a template of one arg):
00037 // GenScatterHierarchy<TList, Unit>
00038 // The generated class inherits all classes generated by instantiating the 
00039 // template 'Unit' with the types contained in TList 
00041 
00042     namespace Private
00043     {
00044         // The following type helps to overcome subtle flaw in the original 
00045         // implementation of GenScatterHierarchy. 
00046         // The flaw is revealed when the input type list of GenScatterHierarchy 
00047         // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). 
00048         // In this case GenScatterHierarchy will contain multiple bases of the same 
00049         // type and some of them will not be reachable (per 10.3).
00050         // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)>
00051         // is not reachable in any way!
00052         template<class, class> 
00053         struct ScatterHierarchyTag;
00054     }
00055 
00056     template <class TList, template <class> class Unit>
00057     class GenScatterHierarchy;
00058      
00059     template <class T1, class T2, template <class> class Unit>
00060     class GenScatterHierarchy<Typelist<T1, T2>, Unit>
00061         : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit>
00062         , public GenScatterHierarchy<T2, Unit>
00063     {
00064     public:
00065         typedef Typelist<T1, T2> TList;
00066         // Insure that LeftBase is unique and therefore reachable
00067         typedef GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> LeftBase;
00068         typedef GenScatterHierarchy<T2, Unit> RightBase;
00069         template <typename T> struct Rebind
00070         {
00071             typedef Unit<T> Result;
00072         };
00073     };
00074      
00075     // In the middle *unique* class that resolve possible ambiguity
00076     template <class T1, class T2, template <class> class Unit>
00077     class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> 
00078         : public GenScatterHierarchy<T1, Unit>
00079     {
00080     };
00081 
00082     template <class AtomicType, template <class> class Unit>
00083     class GenScatterHierarchy : public Unit<AtomicType>
00084     {
00085         typedef Unit<AtomicType> LeftBase;
00086         template <typename T> struct Rebind
00087         {
00088             typedef Unit<T> Result;
00089         };
00090     };
00091     
00092     template <template <class> class Unit>
00093     class GenScatterHierarchy<NullType, Unit>
00094     {
00095         template <typename T> struct Rebind
00096         {
00097             typedef Unit<T> Result;
00098         };
00099     };
00100      
00102 // function template Field
00103 // Accesses a field in an object of a type generated with GenScatterHierarchy
00104 // Invocation (obj is an object of a type H generated with GenScatterHierarchy,
00105 //     T is a type in the typelist used to generate H):
00106 // Field<T>(obj)
00107 // returns a reference to Unit<T>, where Unit is the template used to generate H 
00109 
00110     template <class T, class H>
00111     typename H::template Rebind<T>::Result& Field(H& obj)
00112     {
00113         return obj;
00114     }
00115      
00116     template <class T, class H>
00117     const typename H::template Rebind<T>::Result& Field(const H& obj)
00118     {
00119         return obj;
00120     }
00121      
00123 // function template TupleUnit
00124 // The building block of tuples 
00126 
00127     template <class T>
00128     struct TupleUnit
00129     {
00130         T value_;
00131         operator T&() { return value_; }
00132         operator const T&() const { return value_; }
00133     };
00134 
00136 // class template Tuple
00137 // Implements a tuple class that holds a number of values and provides field 
00138 //     access to them via the Field function (below) 
00140 
00141     template <class TList>
00142     struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
00143     {
00144     };
00145 
00147 // helper class template FieldHelper
00148 // See Field below
00150 
00151     template <class H, unsigned int i> struct FieldHelper;
00152     
00153     template <class H>
00154     struct FieldHelper<H, 0>
00155     {
00156         typedef typename H::TList::Head ElementType;
00157         typedef typename H::template Rebind<ElementType>::Result UnitType;
00158         
00159         enum
00160         {
00161             isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
00162             isConst = TypeTraits<H>::isConst
00163         };
00164 
00165         typedef const typename H::LeftBase ConstLeftBase;
00166         
00167         typedef typename Select<isConst, ConstLeftBase, 
00168             typename H::LeftBase>::Result LeftBase;
00169             
00170         typedef typename Select<isTuple, ElementType, 
00171             UnitType>::Result UnqualifiedResultType;
00172 
00173         typedef typename Select<isConst, const UnqualifiedResultType,
00174                         UnqualifiedResultType>::Result ResultType;
00175             
00176         static ResultType& Do(H& obj)
00177         {
00178             LeftBase& leftBase = obj;
00179             return leftBase;
00180         }
00181     };
00182 
00183     template <class H, unsigned int i>
00184     struct FieldHelper
00185     {
00186         typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
00187         typedef typename H::template Rebind<ElementType>::Result UnitType;
00188         
00189         enum
00190         {
00191             isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
00192             isConst = TypeTraits<H>::isConst
00193         };
00194 
00195         typedef const typename H::RightBase ConstRightBase;
00196         
00197         typedef typename Select<isConst, ConstRightBase, 
00198             typename H::RightBase>::Result RightBase;
00199 
00200         typedef typename Select<isTuple, ElementType, 
00201             UnitType>::Result UnqualifiedResultType;
00202 
00203         typedef typename Select<isConst, const UnqualifiedResultType,
00204                         UnqualifiedResultType>::Result ResultType;
00205             
00206         static ResultType& Do(H& obj)
00207         {
00208             RightBase& rightBase = obj;
00209             return FieldHelper<RightBase, i - 1>::Do(rightBase);
00210         }
00211     };
00212 
00214 // function template Field
00215 // Accesses a field in an object of a type generated with GenScatterHierarchy
00216 // Invocation (obj is an object of a type H generated with GenScatterHierarchy,
00217 //     i is the index of a type in the typelist used to generate H):
00218 // Field<i>(obj)
00219 // returns a reference to Unit<T>, where Unit is the template used to generate H
00220 //     and T is the i-th type in the typelist 
00222 
00223     template <int i, class H>
00224     typename FieldHelper<H, i>::ResultType&
00225     Field(H& obj)
00226     {
00227         return FieldHelper<H, i>::Do(obj);
00228     }
00229         
00230 //    template <int i, class H>
00231 //    const typename FieldHelper<H, i>::ResultType&
00232 //    Field(const H& obj)
00233 //    {
00234 //        return FieldHelper<H, i>::Do(obj);
00235 //    }
00236         
00238 // class template GenLinearHierarchy
00239 // Generates a linear hierarchy starting from a typelist and a template
00240 // Invocation (TList is a typelist, Unit is a template of two args):
00241 // GenScatterHierarchy<TList, Unit>
00243 
00244     template
00245     <
00246         class TList,
00247         template <class AtomicType, class Base> class Unit,
00248         class Root = EmptyType
00249     >
00250     class GenLinearHierarchy;
00251     
00252     template
00253     <
00254         class T1,
00255         class T2,
00256         template <class, class> class Unit,
00257         class Root
00258     >
00259     class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
00260         : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
00261     {
00262     };
00263 
00264     template
00265     <
00266         class T,
00267         template <class, class> class Unit,
00268         class Root
00269     >
00270     class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
00271         : public Unit<T, Root>
00272     {
00273     };
00274 
00275     template
00276     <
00277         template <class, class> class Unit,
00278         class Root
00279     >
00280     class GenLinearHierarchy<NullType , Unit, Root>
00281         : public Root // is this better: Unit<NullType, Root> ?
00282     {
00283     };
00284 
00285 #if defined(_MSC_VER) && _MSC_VER >= 1300
00286 #pragma warning( pop ) 
00287 #endif
00288 }   // namespace Loki
00289 
00290 #endif // end file guardian
00291 

Generated on Sun Feb 25 16:52:26 2007 for Loki by  doxygen 1.5.1-p1