//////////////////////////////////////////////////////////////////////////////// // 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-Welsey Longman make no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// // Last update: May 19, 2002 #ifdef _MSC_VER #pragma once #pragma warning( push ) // 'class1' : base-class 'class2' is already a base-class of 'class3' #pragma warning( disable : 4584 ) #endif // _MSC_VER #ifndef HIERARCHYGENERATORS_INC_ #define HIERARCHYGENERATORS_INC_ #include "Typelist.h" #include "TypeTraits.h" #include "EmptyType.h" namespace Loki { //////////////////////////////////////////////////////////////////////////////// // class template GenScatterHierarchy // Generates a scattered hierarchy starting from a typelist and a template // Invocation (TList is a typelist, Model is a template of one arg): // GenScatterHierarchy // The generated class inherits all classes generated by instantiating the // template 'Model' with the types contained in TList //////////////////////////////////////////////////////////////////////////////// template class Unit> class GenScatterHierarchy; namespace Private { // for some reason VC7 needs the base definition altough not in use template struct GenScatterHierarchyHelper1 { template class Unit> struct In { typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result; }; }; template struct GenScatterHierarchyHelper2 { template class Unit> struct In { typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result; }; }; template <> struct GenScatterHierarchyHelper1 { template class Unit> struct In { typedef GenScatterHierarchy Result; }; }; template <> struct GenScatterHierarchyHelper2 { template class Unit> struct In { typedef GenScatterHierarchy Result; }; }; template <> struct GenScatterHierarchyHelper1 { template class Unit> struct In { typedef Unit Result; }; }; template <> struct GenScatterHierarchyHelper2 { template class Unit> struct In { struct Result {}; }; }; template <> struct GenScatterHierarchyHelper1 { template class Unit> struct In { struct Result {}; }; }; template <> struct GenScatterHierarchyHelper2 { template class Unit> struct In { struct Result {}; }; }; } // namespace Private template class Unit> class GenScatterHierarchy : public Private::GenScatterHierarchyHelper1 < typename TL::is_Typelist::type_tag > ::template In::Result , public Private::GenScatterHierarchyHelper2 < typename TL::is_Typelist::type_tag > ::template In::Result { public: typedef typename Private::GenScatterHierarchyHelper1 < typename TL::is_Typelist::type_tag > ::template In::Result LeftBase; typedef typename Private::GenScatterHierarchyHelper2 < typename TL::is_Typelist::type_tag > ::template In::Result RightBase; typedef typename Select < TL::is_Typelist::value, T, void > ::Result TList; template struct Rebind { typedef Unit 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(obj) // returns a reference to Unit, where Unit is the template used to generate H //////////////////////////////////////////////////////////////////////////////// template typename H::template Rebind::Result & Field(H& obj) { return obj; } template typename H::template Rebind::Result const & Field(H const & obj) { return obj; } //////////////////////////////////////////////////////////////////////////////// // function template TupleUnit // The building block of tuples //////////////////////////////////////////////////////////////////////////////// template 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 struct Tuple : public GenScatterHierarchy { }; //////////////////////////////////////////////////////////////////////////////// // helper class template FieldHelper // See Field below //////////////////////////////////////////////////////////////////////////////// template struct FieldHelper { template struct In { private: typedef typename TL::TypeAt::Result ElementType; typedef typename H::template Rebind::Result UnitType; enum { isConst = TypeTraits::isConst }; typedef typename Select < isConst, const typename H::RightBase, typename H::RightBase > ::Result RightBase; typedef typename Select < SameType >::value, ElementType, UnitType > ::Result UnqualifiedResultType; public: typedef typename Select < isConst, const UnqualifiedResultType, UnqualifiedResultType > ::Result ResultType; static ResultType& Do(H& obj) { RightBase& rightBase = obj; return FieldHelper::template In::Do(rightBase); } }; }; template <> struct FieldHelper<0> { template struct In { private: typedef typename H::TList::Head ElementType; typedef typename H::template Rebind::Result UnitType; enum { isConst = TypeTraits::isConst }; typedef typename Select < isConst, const typename H::LeftBase, typename H::LeftBase > ::Result LeftBase; typedef typename Select < SameType >::value, ElementType, UnitType > ::Result UnqualifiedResultType; public: typedef typename Select < isConst, const UnqualifiedResultType, UnqualifiedResultType > ::Result ResultType; static ResultType& Do(H& obj) { LeftBase& leftBase = obj; return leftBase; } }; }; //////////////////////////////////////////////////////////////////////////////// // 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(obj) // returns a reference to Unit, where Unit is the template used to generate H // and T is the i-th type in the typelist //////////////////////////////////////////////////////////////////////////////// template typename FieldHelper::template In::ResultType& Field(H& obj) { return FieldHelper::template In::Do(obj); } //////////////////////////////////////////////////////////////////////////////// // class template GenLinearHierarchy // Generates a linear hierarchy starting from a typelist and a template // Invocation (TList is a typelist, Model is a template of two args): // GenLinearHierarchy //////////////////////////////////////////////////////////////////////////////// template < class TList, template class Unit, class Root = EmptyType > class GenLinearHierarchy; namespace Private { template struct GenLinearHierarchyHelper { template class Unit, class Root> struct In { typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result; }; }; template <> struct GenLinearHierarchyHelper { template class Unit, class Root> struct In { private: typedef typename TList::Head Head; typedef typename TList::Tail Tail; public: typedef Unit< Head, GenLinearHierarchy > Result; }; }; template <> struct GenLinearHierarchyHelper { template class Unit, class Root> struct In { private: typedef typename TList::Head Head; public: typedef Unit Result; }; }; } // namespace Private template < class TList, template class Unit, class Root > class GenLinearHierarchy : public Private::GenLinearHierarchyHelper < typename TL::is_Typelist::type_tag > ::template In::Result { ASSERT_TYPELIST(TList); // TList must not be NullType public: typedef typename Private::GenLinearHierarchyHelper < typename TL::is_Typelist::type_tag > ::template In::Result LinBase; }; } // namespace Loki //////////////////////////////////////////////////////////////////////////////// // Change log: // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) //////////////////////////////////////////////////////////////////////////////// #endif // HIERARCHYGENERATORS_INC_ #ifdef _MSC_VER #pragma warning( pop ) #endif // _MSC_VER