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