diff options
Diffstat (limited to 'shared/loki/HierarchyGenerators.h')
-rw-r--r-- | shared/loki/HierarchyGenerators.h | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/shared/loki/HierarchyGenerators.h b/shared/loki/HierarchyGenerators.h new file mode 100644 index 00000000..3fa11ffc --- /dev/null +++ b/shared/loki/HierarchyGenerators.h @@ -0,0 +1,291 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_HIERARCHYGENERATORS_INC_ +#define LOKI_HIERARCHYGENERATORS_INC_ + +// $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +#include "Typelist.h" +#include "TypeTraits.h" +#include "EmptyType.h" + +namespace Loki +{ +#if defined(_MSC_VER) && _MSC_VER >= 1300 +#pragma warning( push ) + // 'class1' : base-class 'class2' is already a base-class of 'class3' +#pragma warning( disable : 4584 ) +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// class template GenScatterHierarchy +// Generates a scattered hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Unit is a template of one arg): +// GenScatterHierarchy<TList, Unit> +// The generated class inherits all classes generated by instantiating the +// template 'Unit' with the types contained in TList +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + // The following type helps to overcome subtle flaw in the original + // implementation of GenScatterHierarchy. + // The flaw is revealed when the input type list of GenScatterHierarchy + // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). + // In this case GenScatterHierarchy will contain multiple bases of the same + // type and some of them will not be reachable (per 10.3). + // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)> + // is not reachable in any way! + template<class, class> + struct ScatterHierarchyTag; + } + + template <class TList, template <class> class Unit> + class GenScatterHierarchy; + + template <class T1, class T2, template <class> class Unit> + class GenScatterHierarchy<Typelist<T1, T2>, Unit> + : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> + , public GenScatterHierarchy<T2, Unit> + { + public: + typedef Typelist<T1, T2> TList; + // Insure that LeftBase is unique and therefore reachable + typedef GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> LeftBase; + typedef GenScatterHierarchy<T2, Unit> RightBase; + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + + // In the middle *unique* class that resolve possible ambiguity + template <class T1, class T2, template <class> class Unit> + class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> + : public GenScatterHierarchy<T1, Unit> + { + }; + + template <class AtomicType, template <class> class Unit> + class GenScatterHierarchy : public Unit<AtomicType> + { + typedef Unit<AtomicType> LeftBase; + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + + template <template <class> class Unit> + class GenScatterHierarchy<NullType, Unit> + { + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Field +// Accesses a field in an object of a type generated with GenScatterHierarchy +// Invocation (obj is an object of a type H generated with GenScatterHierarchy, +// T is a type in the typelist used to generate H): +// Field<T>(obj) +// returns a reference to Unit<T>, where Unit is the template used to generate H +//////////////////////////////////////////////////////////////////////////////// + + template <class T, class H> + typename H::template Rebind<T>::Result& Field(H& obj) + { + return obj; + } + + template <class T, class H> + const typename H::template Rebind<T>::Result& Field(const H& obj) + { + return obj; + } + +//////////////////////////////////////////////////////////////////////////////// +// function template TupleUnit +// The building block of tuples +//////////////////////////////////////////////////////////////////////////////// + + template <class T> + struct TupleUnit + { + T value_; + operator T&() { return value_; } + operator const T&() const { return value_; } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Tuple +// Implements a tuple class that holds a number of values and provides field +// access to them via the Field function (below) +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> + struct Tuple : public GenScatterHierarchy<TList, TupleUnit> + { + }; + +//////////////////////////////////////////////////////////////////////////////// +// helper class template FieldHelper +// See Field below +//////////////////////////////////////////////////////////////////////////////// + + template <class H, unsigned int i> struct FieldHelper; + + template <class H> + struct FieldHelper<H, 0> + { + typedef typename H::TList::Head ElementType; + typedef typename H::template Rebind<ElementType>::Result UnitType; + + enum + { + isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, + isConst = TypeTraits<H>::isConst + }; + + typedef const typename H::LeftBase ConstLeftBase; + + typedef typename Select<isConst, ConstLeftBase, + typename H::LeftBase>::Result LeftBase; + + typedef typename Select<isTuple, ElementType, + UnitType>::Result UnqualifiedResultType; + + typedef typename Select<isConst, const UnqualifiedResultType, + UnqualifiedResultType>::Result ResultType; + + static ResultType& Do(H& obj) + { + LeftBase& leftBase = obj; + return leftBase; + } + }; + + template <class H, unsigned int i> + struct FieldHelper + { + typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType; + typedef typename H::template Rebind<ElementType>::Result UnitType; + + enum + { + isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, + isConst = TypeTraits<H>::isConst + }; + + typedef const typename H::RightBase ConstRightBase; + + typedef typename Select<isConst, ConstRightBase, + typename H::RightBase>::Result RightBase; + + typedef typename Select<isTuple, ElementType, + UnitType>::Result UnqualifiedResultType; + + typedef typename Select<isConst, const UnqualifiedResultType, + UnqualifiedResultType>::Result ResultType; + + static ResultType& Do(H& obj) + { + RightBase& rightBase = obj; + return FieldHelper<RightBase, i - 1>::Do(rightBase); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Field +// Accesses a field in an object of a type generated with GenScatterHierarchy +// Invocation (obj is an object of a type H generated with GenScatterHierarchy, +// i is the index of a type in the typelist used to generate H): +// Field<i>(obj) +// returns a reference to Unit<T>, where Unit is the template used to generate H +// and T is the i-th type in the typelist +//////////////////////////////////////////////////////////////////////////////// + + template <int i, class H> + typename FieldHelper<H, i>::ResultType& + Field(H& obj) + { + return FieldHelper<H, i>::Do(obj); + } + +// template <int i, class H> +// const typename FieldHelper<H, i>::ResultType& +// Field(const H& obj) +// { +// return FieldHelper<H, i>::Do(obj); +// } + +//////////////////////////////////////////////////////////////////////////////// +// class template GenLinearHierarchy +// Generates a linear hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Unit is a template of two args): +// GenScatterHierarchy<TList, Unit> +//////////////////////////////////////////////////////////////////////////////// + + template + < + class TList, + template <class AtomicType, class Base> class Unit, + class Root = EmptyType + > + class GenLinearHierarchy; + + template + < + class T1, + class T2, + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root> + : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> > + { + }; + + template + < + class T, + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root> + : public Unit<T, Root> + { + }; + + template + < + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<NullType , Unit, Root> + : public Root // is this better: Unit<NullType, Root> ? + { + }; + +#if defined(_MSC_VER) && _MSC_VER >= 1300 +#pragma warning( pop ) +#endif +} // namespace Loki + +#endif // end file guardian + |