www.pudn.com > Loki.rar > HierarchyGenerators.h


//////////////////////////////////////////////////////////////////////////////// 
// 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