b53b3265e4
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@108 7ec92016-0320-0410-acc4-a06ded1c099a
423 lines
12 KiB
C++
423 lines
12 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// 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<TList, Model>
|
|
// The generated class inherits all classes generated by instantiating the
|
|
// template 'Model' with the types contained in TList
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
template <typename T, template <typename> class Unit>
|
|
class GenScatterHierarchy;
|
|
|
|
namespace Private
|
|
{
|
|
// for some reason VC7 needs the base definition altough not in use
|
|
template <typename TListTag>
|
|
struct GenScatterHierarchyHelper1
|
|
{
|
|
template <typename T, template <typename> class Unit>
|
|
struct In
|
|
{
|
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
|
};
|
|
};
|
|
|
|
template <typename TListTag>
|
|
struct GenScatterHierarchyHelper2
|
|
{
|
|
template <typename T, template <typename> class Unit>
|
|
struct In
|
|
{
|
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
|
};
|
|
};
|
|
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper1<TL::Typelist_tag>
|
|
{
|
|
template <class TList, template <typename> class Unit>
|
|
struct In
|
|
{
|
|
typedef GenScatterHierarchy<typename TList::Head, Unit> Result;
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper2<TL::Typelist_tag>
|
|
{
|
|
template <class TList, template <typename> class Unit>
|
|
struct In
|
|
{
|
|
typedef GenScatterHierarchy<typename TList::Tail, Unit> Result;
|
|
};
|
|
};
|
|
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper1<TL::NoneList_tag>
|
|
{
|
|
template <typename AtomicType, template <typename> class Unit>
|
|
struct In { typedef Unit<AtomicType> Result; };
|
|
};
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper2<TL::NoneList_tag>
|
|
{
|
|
template <typename AtomicType, template <typename> class Unit>
|
|
struct In { struct Result {}; };
|
|
};
|
|
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper1<TL::NullType_tag>
|
|
{
|
|
template <class TList, template <typename> class Unit>
|
|
struct In { struct Result {}; };
|
|
};
|
|
|
|
template <>
|
|
struct GenScatterHierarchyHelper2<TL::NullType_tag>
|
|
{
|
|
template <class TList, template <typename> class Unit>
|
|
struct In { struct Result {}; };
|
|
};
|
|
|
|
} // namespace Private
|
|
|
|
template <typename T, template <typename> class Unit>
|
|
class GenScatterHierarchy
|
|
: public Private::GenScatterHierarchyHelper1
|
|
<
|
|
typename TL::is_Typelist<T>::type_tag
|
|
>
|
|
::template In<T, Unit>::Result
|
|
|
|
, public Private::GenScatterHierarchyHelper2
|
|
<
|
|
typename TL::is_Typelist<T>::type_tag
|
|
>
|
|
::template In<T, Unit>::Result
|
|
{
|
|
public:
|
|
|
|
typedef typename Private::GenScatterHierarchyHelper1
|
|
<
|
|
typename TL::is_Typelist<T>::type_tag
|
|
>
|
|
::template In<T, Unit>::Result LeftBase;
|
|
|
|
typedef typename Private::GenScatterHierarchyHelper2
|
|
<
|
|
typename TL::is_Typelist<T>::type_tag
|
|
>
|
|
::template In<T, Unit>::Result RightBase;
|
|
|
|
|
|
typedef typename Select
|
|
<
|
|
TL::is_Typelist<T>::value, T, void
|
|
>
|
|
::Result TList;
|
|
|
|
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>
|
|
typename H::template Rebind<T>::Result const &
|
|
Field(H const & 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 <unsigned int i>
|
|
struct FieldHelper
|
|
{
|
|
template<class H>
|
|
struct In
|
|
{
|
|
private:
|
|
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
|
|
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
|
|
|
enum { isConst = TypeTraits<H>::isConst };
|
|
|
|
typedef typename Select
|
|
<
|
|
isConst,
|
|
const typename H::RightBase,
|
|
typename H::RightBase
|
|
>
|
|
::Result RightBase;
|
|
|
|
typedef typename Select
|
|
<
|
|
IsSameType<UnitType, TupleUnit<ElementType> >::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<i - 1>::template In<RightBase>::Do(rightBase);
|
|
}
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct FieldHelper<0>
|
|
{
|
|
template<class H>
|
|
struct In
|
|
{
|
|
private:
|
|
typedef typename H::TList::Head ElementType;
|
|
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
|
|
|
enum { isConst = TypeTraits<H>::isConst };
|
|
|
|
typedef typename Select
|
|
<
|
|
isConst,
|
|
const typename H::LeftBase,
|
|
typename H::LeftBase
|
|
>
|
|
::Result LeftBase;
|
|
|
|
typedef typename Select
|
|
<
|
|
IsSameType<UnitType, TupleUnit<ElementType> >::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<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 <unsigned int i, class H>
|
|
typename FieldHelper<i>::template In<H>::ResultType&
|
|
Field(H& obj)
|
|
{
|
|
return FieldHelper<i>::template In<H>::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<TList, Model, Root>
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template
|
|
<
|
|
class TList,
|
|
template <class AtomicType, class UnitBase> class Unit,
|
|
class Root = EmptyType
|
|
>
|
|
class GenLinearHierarchy;
|
|
|
|
namespace Private
|
|
{
|
|
|
|
template <typename TListTag>
|
|
struct GenLinearHierarchyHelper
|
|
{
|
|
template<class TList, template <class, class> class Unit, class Root>
|
|
struct In
|
|
{
|
|
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct GenLinearHierarchyHelper<TL::Typelist_tag>
|
|
{
|
|
template<class TList, template <class, class> class Unit, class Root>
|
|
struct In
|
|
{
|
|
private:
|
|
typedef typename TList::Head Head;
|
|
typedef typename TList::Tail Tail;
|
|
|
|
public:
|
|
typedef Unit< Head, GenLinearHierarchy<Tail, Unit, Root> > Result;
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct GenLinearHierarchyHelper<TL::NullType_tag>
|
|
{
|
|
template<class TList, template <class, class> class Unit, class Root>
|
|
struct In
|
|
{
|
|
private:
|
|
typedef typename TList::Head Head;
|
|
|
|
public:
|
|
typedef Unit<Head, Root> Result;
|
|
};
|
|
};
|
|
|
|
} // namespace Private
|
|
|
|
template
|
|
<
|
|
class TList,
|
|
template <class AtomicType, class UnitBase> class Unit,
|
|
class Root
|
|
>
|
|
class GenLinearHierarchy
|
|
: public Private::GenLinearHierarchyHelper
|
|
<
|
|
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
|
>
|
|
::template In<TList, Unit, Root>::Result
|
|
{
|
|
ASSERT_TYPELIST(TList); // TList must not be NullType
|
|
|
|
public:
|
|
typedef typename Private::GenLinearHierarchyHelper
|
|
<
|
|
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
|
>
|
|
::template In<TList, Unit, Root>::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
|
|
|