📄 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-Wesley 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: Mar 08, 2003
#ifndef HIERARCHYGENERATORS_INC_
#define HIERARCHYGENERATORS_INC_
#define IS_TYPELIST(TList) TL::Private::IsTypelist<TList>
#include "Typelist.h"
#include "TypeTraits.h"
#include "EmptyType.h"
#include "MSVC6Helpers.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
////////////////////////////////////////////////////////////////////////////////
// VC 6.0 changes:
// * Unit is no longer a template template parameter.
// * For every concrete unit-template there must be a normal class containing
// a nested-template class called In. In should only contain a typedef to the
// concrete Unit.
//
// Using the originial library one would write something like this:
// class Foo {};
// template <class T> struct TestUnit {};
// void Func(TestUnit<Foo>);
// int main()
// {
// GenScatterHierarchy<Typelist<Foo, NullType>, TestUnit> obj;
// Func(obj); // calls Func(TestUnit<Foo>)
// }
//
// Using this port the code would become:
// class Foo {};
// template <class T> struct TestUnit {};
// struct TestUnitWrapper
// {
// template <class T> struct In {typedef TestUnit<T> type};
// };
// void Func(TestUnit<Foo>);
// int main()
// {
// GenScatterHierarchy<Typelist<Foo, NullType>, TestUnitWrapper> obj;
// Func(obj); // calls Func(TestUnit<Foo>)
// }
//
// Not very nice, i know :-(
//
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
// (http://lists.boost.org/MailArchives/boost/msg20915.php)
//
// Update:
// -------
// The first version of GenScatterHierarchy did not work with typelists
// containing equal types. The MSVC 6.0 erroneously complains about
// inaccessible base-classes (error C2584).
// This new version adds Dummy-classes to the left branch of the generated
// hierarchy to workaround this VC-Bug.
// It creates hierarchies like this:
//
// Holder<int> NullType
// \ /
//Holder<int> GenScatter<int> GenScatter<NullType>
// \ \ /
//VC_InaccessibleBase InheritFromTo
// \ |
//GenScatter<int> GenScatter<TYPELIST_1(int)>
// \ /
// InheritFromTo
// |
// |
//GenScatter<TYPELIST_2(int, int)>
//
// Of course this version of GenScatterHierarchy generates a lot more
// classes (5*n) than Alexandrescu's original implementation (3*n)
//
template <class TList, class Unit> class GenScatterHierarchy;
namespace Private
{
template <class T, class U>
struct InheritFromTwo : public T, public U
{
inline InheritFromTwo() : T(), U() {}
};
template <int tag>
struct GenScatterImpl;
// Specialization for a general typelist
template <>
struct GenScatterImpl<TL::Private::Typelist_ID>
{
template <class T, class MetaFunctionWrapper>
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
{
typedef
InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>, typename T::Tail>,
GenScatterHierarchy<typename T::Tail,
MetaFunctionWrapper>
> type;
typedef VC_InaccessibleBase<GenScatterHierarchy<typename T::Head, MetaFunctionWrapper>,typename T::Tail> LeftBase;
typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase;
};
};
// Specialization for a typelist with only one element
template <>
struct GenScatterImpl<TL::Private::AtomList_ID>
{
template <class T, class MetaFunctionWrapper>
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
{
// for the last Holder-class no dummy class is needed.
typedef
InheritFromTwo < GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>,
GenScatterHierarchy<NullType,
MetaFunctionWrapper>
> type;
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
typedef GenScatterHierarchy<NullType, MetaFunctionWrapper> RightBase;
};
};
// Specialization for a single type
template <>
struct GenScatterImpl<TL::Private::NoneList_ID>
{
template <class AtomicType, class MetaFunctionWrapper>
struct In
{
typedef typename
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
typedef type LeftBase;
typedef EmptyType RightBase;
//typedef AtomicType::THIS_SELECTED bla;
};
};
// Specialization for NullType
template <>
struct GenScatterImpl<TL::Private::NullType_ID>
{
template <class NullTypeList, class MetaFunctionWrapper>
struct In
{
typedef EmptyType type;
typedef type LeftBase;
typedef type RightBase;
};
};
} // end namespace Private
template <class T, class Unit>
class GenScatterHierarchy : public Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::type
{
public:
typedef typename Select
<
TL::Private::IsTypelist<T>::value, T, void
>::Result TList;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::LeftBase LeftBase;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::RightBase RightBase;
template <typename U> struct Rebind
{
typedef ApplyInnerType<Unit, U>::type 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 TList, class UnitWrapper>
typename ApplyInnerType<UnitWrapper, T>::type&
Field(GenScatterHierarchy<TList, UnitWrapper>& obj,Type2Type<T>* = (Type2Type<T>*)0)
{
return obj;
}
template <class T, class TList, class UnitWrapper>
const typename ApplyInnerType<UnitWrapper, T>::type&
Field(const GenScatterHierarchy<TList, UnitWrapper>& obj, Type2Type<T>* = (Type2Type<T>*)0)
{
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)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
struct TupleUnitWrapper
{
template <class T>
struct In
{
typedef TupleUnit<T> type;
};
};
}
template <class TList>
struct Tuple : public GenScatterHierarchy<TList, Private::TupleUnitWrapper>
{
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -