Benjamin Kaufmann's port
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@86 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
6539637357
commit
ca94249f94
23 changed files with 9419 additions and 0 deletions
217
MSVC/1200/AbstractFactory.h
Normal file
217
MSVC/1200/AbstractFactory.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Oct 24, 2002
|
||||
// replaced all template template parameters with 'normal' parameters
|
||||
// For each Factory-Unit there is now a wrapper-class (non template class)
|
||||
// containing a nested template class called In which
|
||||
// provides a typedef (type) to the real unit-class.
|
||||
// Use one of the wrapper-classes to instantiate a factory.
|
||||
//
|
||||
// Covariant return types had to go, too.
|
||||
|
||||
#ifndef ABSTRACTFACTORY_INC_
|
||||
#define ABSTRACTFACTORY_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeManip.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
#include "MSVC6Helpers.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#define ETAS_HELPER(Type) ((Type*)0)
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactoryUnit
|
||||
// The building block of an Abstract Factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class AbstractFactoryUnit
|
||||
{
|
||||
public:
|
||||
virtual T* DoCreate(Type2Type<T>) = 0;
|
||||
virtual ~AbstractFactoryUnit() {}
|
||||
};
|
||||
|
||||
// Wrapper for AbstractFactoryUnit.
|
||||
struct AbstractFactoryUnitWrapper
|
||||
{
|
||||
template <class T>
|
||||
struct In
|
||||
{
|
||||
typedef AbstractFactoryUnit<T> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactory
|
||||
// Defines an Abstract Factory interface starting from a typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// VC 6.0 changes:
|
||||
// Because the VC 6.0 does not support explicit template argument specification (14.8.1)
|
||||
// the member-function Create takes a dummy argument of type T* whose sole
|
||||
// responsibility is to help the compiler in deducing the type of T.
|
||||
// Using this port the call:
|
||||
// ConcProduct* p = aFactory.Create<ConcProduct>();
|
||||
// therefore becomes:
|
||||
// ConcProduct* p = aFactory.Create((ConcProduct*)0);
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
class Unit = AbstractFactoryUnitWrapper
|
||||
>
|
||||
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
|
||||
{
|
||||
public:
|
||||
typedef TList ProductList;
|
||||
|
||||
template <class T> T* Create(T* DeduceHelper)
|
||||
{
|
||||
ApplyInnerType<Unit, T>::type& unit = *this;
|
||||
return unit.DoCreate(Type2Type<T>());
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template OpNewFactoryUnit
|
||||
// Creates an object by invoking the new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class OpNewFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
// VC does not support covariant return types
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
return new ConcreteProduct;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for OpNewFactoryUnit
|
||||
struct OpNewFactoryUnitWrapper
|
||||
{
|
||||
template <class T, class Base>
|
||||
struct In
|
||||
{
|
||||
typedef OpNewFactoryUnit<T, Base> type;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PrototypeFactoryUnit
|
||||
// Creates an object by cloning a prototype
|
||||
// There is a difference between the implementation herein and the one described
|
||||
// in the book: GetPrototype and SetPrototype use the helper friend
|
||||
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
|
||||
// name hiding issues. Plus, GetPrototype takes a reference to pointer
|
||||
// instead of returning the pointer by value.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class PrototypeFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
|
||||
PrototypeFactoryUnit(AbstractProduct* p = 0)
|
||||
: pPrototype_(p)
|
||||
{}
|
||||
|
||||
friend void DoGetPrototype(const PrototypeFactoryUnit& me,
|
||||
AbstractProduct*& pPrototype)
|
||||
{ pPrototype = me.pPrototype_; }
|
||||
|
||||
friend void DoSetPrototype(PrototypeFactoryUnit& me,
|
||||
AbstractProduct* pObj)
|
||||
{ me.pPrototype_ = pObj; }
|
||||
|
||||
template <class U>
|
||||
void GetPrototype(AbstractProduct*& p)
|
||||
{ return DoGetPrototype(*this, p); }
|
||||
|
||||
template <class U>
|
||||
void SetPrototype(U* pObj)
|
||||
{ DoSetPrototype(*this, pObj); }
|
||||
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
assert(pPrototype_);
|
||||
// vc does not support covariant return types thus
|
||||
// Clone *always* returns a base-pointer.
|
||||
// if DoCreate is called from a ConcreteFactory-object we
|
||||
// need to down-cast.
|
||||
// Is the static_cast always safe?
|
||||
return static_cast<AbstractProduct*>(pPrototype_->Clone());
|
||||
}
|
||||
|
||||
private:
|
||||
AbstractProduct* pPrototype_;
|
||||
};
|
||||
|
||||
// Wrapper for PrototypeFactoryUnit
|
||||
struct PrototypeFactoryUnitWrapper
|
||||
{
|
||||
template <class T, class Base>
|
||||
struct In
|
||||
{
|
||||
typedef PrototypeFactoryUnit<T, Base> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConcreteFactory
|
||||
// Implements an AbstractFactory interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractFact,
|
||||
class Creator = OpNewFactoryUnit,
|
||||
class TList = /*VC 6.0 does not like typename here*/ AbstractFact::ProductList
|
||||
>
|
||||
class ConcreteFactory
|
||||
: public GenLinearHierarchy<
|
||||
typename TL::Reverse<TList>::Result, Creator, AbstractFact>
|
||||
{
|
||||
public:
|
||||
typedef typename AbstractFact::ProductList ProductList;
|
||||
typedef TList ConcreteProductList;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ABSTRACTFACTORY_INC_
|
Loading…
Add table
Add a link
Reference in a new issue