Loki/include/loki/HierarchyGenerators.h

299 lines
10 KiB
C
Raw Normal View History

////////////////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////////////////
// $Header:
#ifndef HIERARCHYGENERATORS_INC_
#define HIERARCHYGENERATORS_INC_
#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. 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<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
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
//
// $Log:
////////////////////////////////////////////////////////////////////////////////
#endif // HIERARCHYGENERATORS_INC_