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:
tslettebo 2003-01-06 02:26:33 +00:00
parent 6539637357
commit ca94249f94
23 changed files with 9419 additions and 0 deletions

217
MSVC/1200/AbstractFactory.h Normal file
View 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_

335
MSVC/1200/AssocVector.h Normal file
View file

@ -0,0 +1,335 @@
////////////////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////////////////
#ifndef ASSOCVECTOR_INC_
#define ASSOCVECTOR_INC_
#include <algorithm>
#include <functional>
#include <vector>
#include <utility>
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template AssocVectorCompare
// Used by AssocVector
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class Value, class C>
class AssocVectorCompare : public C
{
typedef std::pair<typename C::first_argument_type, Value>
Data;
typedef typename C::first_argument_type first_argument_type;
public:
AssocVectorCompare()
{}
AssocVectorCompare(const C& src) : C(src)
{}
bool operator()(const first_argument_type& lhs,
const first_argument_type& rhs) const
{ return C::operator()(lhs, rhs); }
bool operator()(const Data& lhs, const Data& rhs) const
{ return operator()(lhs.first, rhs.first); }
bool operator()(const Data& lhs,
const first_argument_type& rhs) const
{ return operator()(lhs.first, rhs); }
bool operator()(const first_argument_type& lhs,
const Data& rhs) const
{ return operator()(lhs, rhs.first); }
};
}
////////////////////////////////////////////////////////////////////////////////
// class template AssocVector
// An associative vector built as a syntactic drop-in replacement for std::map
// BEWARE: AssocVector doesn't respect all map's guarantees, the most important
// being:
// * iterators are invalidated by insert and erase operations
// * the complexity of insert/erase is O(N) not O(log N)
// * value_type is std::pair<K, V> not std::pair<const K, V>
// * iterators are random
////////////////////////////////////////////////////////////////////////////////
template
<
class K,
class V,
class C = std::less<K>,
class A = std::allocator< std::pair<K, V> >
>
class AssocVector
: private std::vector< std::pair<K, V>, A >
, private Private::AssocVectorCompare<V, C>
{
typedef std::vector<std::pair<K, V>, A> Base;
typedef Private::AssocVectorCompare<V, C> MyCompare;
public:
typedef K key_type;
typedef V mapped_type;
typedef typename Base::value_type value_type;
typedef C key_compare;
typedef A allocator_type;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename Base::reverse_iterator reverse_iterator;
typedef typename Base::const_reverse_iterator const_reverse_iterator;
class value_compare
: public std::binary_function<value_type, value_type, bool>
, private key_compare
{
friend class AssocVector;
protected:
value_compare(key_compare pred) : key_compare(pred)
{}
public:
bool operator()(const value_type& lhs, const value_type& rhs) const
{ return key_compare::operator()(lhs.first, rhs.first); }
};
// 23.3.1.1 construct/copy/destroy
explicit AssocVector(const key_compare& comp = key_compare(),
const A& alloc = A())
: Base(alloc), MyCompare(comp)
{}
template <class InputIterator>
AssocVector(InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const A& alloc = A())
: Base(first, last, alloc), MyCompare(comp)
{
MyCompare& me = *this;
std::sort(begin(), end(), me);
}
AssocVector& operator=(const AssocVector& rhs)
{
AssocVector(rhs).swap(*this);
return *this;
}
// iterators:
// The following are here because MWCW gets 'using' wrong
iterator begin() { return Base::begin(); }
const_iterator begin() const { return Base::begin(); }
iterator end() { return Base::end(); }
const_iterator end() const { return Base::end(); }
reverse_iterator rbegin() { return Base::rbegin(); }
const_reverse_iterator rbegin() const { return Base::rbegin(); }
reverse_iterator rend() { return Base::rend(); }
const_reverse_iterator rend() const { return Base::rend(); }
// capacity:
bool empty() const { return Base::empty(); }
size_type size() const { return Base::size(); }
size_type max_size() { return Base::max_size(); }
// 23.3.1.2 element access:
mapped_type& operator[](const key_type& key)
{ return insert(value_type(key, mapped_type())).first->second; }
// modifiers:
std::pair<iterator, bool> insert(const value_type& val)
{
bool found(true);
iterator i(lower_bound(val.first));
if (i == end() || operator()(val.first, i->first))
{
i = Base::insert(i, val);
found = false;
}
return std::make_pair(i, !found);
}
iterator insert(iterator pos, const value_type& val)
{
if (pos != end() && operator()(*pos, val) &&
(pos == end() - 1 ||
!operator()(val, pos[1]) &&
operator()(pos[1], val)))
{
return Base::insert(pos, val);
}
return insert(val).first;
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{ for (; first != last; ++first) insert(*first); }
void erase(iterator pos)
{ Base::erase(pos); }
size_type erase(const key_type& k)
{
iterator i(find(k));
if (i == end()) return 0;
erase(i);
return 1;
}
void erase(iterator first, iterator last)
{ Base::erase(first, last); }
void swap(AssocVector& other)
{
using std::swap;
Base::swap(other);
MyCompare& me = *this;
MyCompare& rhs = other;
swap(me, rhs);
}
void clear()
{ Base::clear(); }
// observers:
key_compare key_comp() const
{ return *this; }
value_compare value_comp() const
{
const key_compare& comp = *this;
return value_compare(comp);
}
// 23.3.1.3 map operations:
iterator find(const key_type& k)
{
iterator i(lower_bound(k));
if (i != end() && operator()(k, i->first))
{
i = end();
}
return i;
}
const_iterator find(const key_type& k) const
{
const_iterator i(lower_bound(k));
if (i != end() && operator()(k, i->first))
{
i = end();
}
return i;
}
size_type count(const key_type& k) const
{ return find(k) != end(); }
iterator lower_bound(const key_type& k)
{
MyCompare& me = *this;
return std::lower_bound(begin(), end(), k, me);
}
const_iterator lower_bound(const key_type& k) const
{
const MyCompare& me = *this;
return std::lower_bound(begin(), end(), k, me);
}
iterator upper_bound(const key_type& k)
{
MyCompare& me = *this;
return std::upper_bound(begin(), end(), k, me);
}
const_iterator upper_bound(const key_type& k) const
{
const MyCompare& me = *this;
return std::upper_bound(begin(), end(), k, me);
}
std::pair<iterator, iterator> equal_range(const key_type& k)
{
MyCompare& me = *this;
return std::equal_range(begin(), end(), k, me);
}
std::pair<const_iterator, const_iterator> equal_range(
const key_type& k) const
{
const MyCompare& me = *this;
return std::equal_range(begin(), end(), k, me);
}
friend bool operator==(const AssocVector& lhs, const AssocVector& rhs)
{
const Base& me = lhs;
return me == rhs;
}
bool operator<(const AssocVector& rhs) const
{
const Base& me = *this;
const Base& yo = rhs;
return me < yo;
}
friend bool operator!=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(lhs == rhs); }
friend bool operator>(const AssocVector& lhs, const AssocVector& rhs)
{ return rhs < lhs; }
friend bool operator>=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(lhs < rhs); }
friend bool operator<=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(rhs < lhs); }
};
// specialized algorithms:
template <class K, class V, class C, class A>
void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
{ lhs.swap(rhs); }
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// May 20, 2001: change operator= - credit due to Cristoph Koegl
// June 11, 2001: remove paren in equal_range - credit due to Cristoph Koegl
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// January 22, 2002: fixed operator= - credit due to Tom Hyer
// June 25, 2002: fixed template insert() - credit due to Robert Minsk
// June 27, 2002: fixed member swap() - credit due to David Brookman
////////////////////////////////////////////////////////////////////////////////
#endif // ASSOCVECTOR_INC_

37
MSVC/1200/EmptyType.h Normal file
View file

@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////////
// 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: June 20, 2001
#ifndef EMPTYTYPE_INC_
#define EMPTYTYPE_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class EmptyType
// Used as a class type that doesn't hold anything
// Useful as a strawman class
////////////////////////////////////////////////////////////////////////////////
class EmptyType {};
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif // EMPTYTYPE_INC_

146
MSVC/1200/Factory.h Normal file
View file

@ -0,0 +1,146 @@
////////////////////////////////////////////////////////////////////////////////
// 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
#ifndef FACTORY_INC_
#define FACTORY_INC_
#include "TypeInfo.h"
#include "AssocVector.h"
#include <exception>
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template DefaultFactoryError
// Manages the "Unknown Type" error in an object factory
////////////////////////////////////////////////////////////////////////////////
struct DefaultFactoryError
{
struct Exception : public std::exception
{
const char* what() const throw() { return "Unknown Type"; }
};
template <typename IdentifierType, class AbstractProduct>
static AbstractProduct* OnUnknownType(IdentifierType)
{
throw Exception();
}
};
////////////////////////////////////////////////////////////////////////////////
// class template Factory
// Implements a generic object factory
////////////////////////////////////////////////////////////////////////////////
template
<
class AbstractProduct,
typename IdentifierType,
typename ProductCreator = AbstractProduct* (*)(),
class FactoryErrorPolicy = DefaultFactoryError
>
class Factory
: public FactoryErrorPolicy
{
public:
bool Register(const IdentifierType& id, ProductCreator creator)
{
return associations_.insert(
IdToProductMap::value_type(id, creator)).second;
}
bool Unregister(const IdentifierType& id)
{
return associations_.erase(id) == 1;
}
AbstractProduct* CreateObject(const IdentifierType& id)
{
typename IdToProductMap::iterator i = associations_.find(id);
if (i != associations_.end())
{
return (i->second)();
}
return OnUnknownType(id);
}
private:
typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
IdToProductMap associations_;
};
////////////////////////////////////////////////////////////////////////////////
// class template CloneFactory
// Implements a generic cloning factory
////////////////////////////////////////////////////////////////////////////////
template
<
class AbstractProduct,
class ProductCreator =
AbstractProduct* (*)(const AbstractProduct*),
class FactoryErrorPolicy = DefaultFactoryError
>
class CloneFactory
: public FactoryErrorPolicy
{
public:
bool Register(const TypeInfo& ti, ProductCreator creator)
{
return associations_.insert(
IdToProductMap::value_type(ti, creator)).second;
}
bool Unregister(const TypeInfo& id)
{
return associations_.erase(id) == 1;
}
AbstractProduct* CreateObject(const AbstractProduct* model)
{
if (model == 0) return 0;
typename IdToProductMap::iterator i =
associations_.find(typeid(*model));
if (i != associations_.end())
{
return (i->second)(model);
}
return OnUnknownType(TypeInfo(typeid(*model)),(AbstractProduct*)0);
}
private:
typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
IdToProductMap associations_;
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 08, 2002: replaced const_iterator with iterator so that self-modifying
// ProductCreators are supported. Also, added a throw() spec to what().
// Credit due to Jason Fischl.
// Oct 24, 2002: ported to MSVC 6 by Benjamin Kaufmann.
// Note: The default error policy is no longer a template-class.
////////////////////////////////////////////////////////////////////////////////
#endif // FACTORY_INC_

2054
MSVC/1200/Functor.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,460 @@
////////////////////////////////////////////////////////////////////////////////
// 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
#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)
template <class TList, class Unit> class GenScatterHierarchy;
namespace Private
{
template <class T, class U>
class InheritFromTwo : public T, public U
{
public:
};
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 < GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>,
GenScatterHierarchy<typename T::Tail,
MetaFunctionWrapper>
> type;
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
typedef GenScatterHierarchy<typename T::Tail, 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;
};
};
// 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 == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
TL::Private::NoneList_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 == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
TL::Private::NoneList_ID
>::template In<T, Unit>::LeftBase LeftBase;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
TL::Private::NoneList_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)
{
return obj;
}
template <class T, class TList, class UnitWrapper>
const typename ApplyInnerType<UnitWrapper, T>::type&
Field(const GenScatterHierarchy<TList, UnitWrapper>& 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)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
struct TupleUnitWrapper
{
template <class T>
struct In
{
typedef TupleUnit<T> type;
};
};
}
template <class TList>
struct Tuple : public GenScatterHierarchy<TList, Private::TupleUnitWrapper>
{
};
////////////////////////////////////////////////////////////////////////////////
// helper class template FieldHelper
// See Field below
////////////////////////////////////////////////////////////////////////////////
template <unsigned int i>
struct FieldHelper
{
template<class H, class Unit>
struct In
{
private:
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
typedef typename ApplyInnerType<Unit, ElementType>::type UnitType;
enum { isConst = TypeTraits<H>::isConst };
typedef typename Select
<
isConst,
const typename H::RightBase,
typename H::RightBase
>
::Result RightBase;
typedef typename Select
<
IsEqualType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
// Must be a template, don't know why.
// If Do is not a template and H& is used as parameter
// MSVC will give a linker error.
template <class T>
static ResultType& Do(T& obj)
{
typedef typename T::RightBase RightBase;
RightBase& rightBase = obj;
return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase);
}
};
};
template <>
struct FieldHelper<0>
{
template<class H, class Unit>
struct In
{
private:
typedef typename H::TList::Head ElementType;
typedef typename ApplyInnerType<Unit, ElementType>::type UnitType;
enum { isConst = TypeTraits<H>::isConst };
typedef typename Select
<
isConst,
const typename H::LeftBase,
typename H::LeftBase
>
::Result LeftBase;
typedef typename Select
<
IsEqualType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
public:
template <class T>
static ResultType& Do(T& 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 TList, class UnitWrapper>
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
Field(GenScatterHierarchy<TList, UnitWrapper>& obj)
{
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
return FieldHelper<i>::template In<H, UnitWrapper>::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):
// GenScatterHierarchy<TList, Model>
////////////////////////////////////////////////////////////////////////////////
// VC 6.0 changes:
// see GenScatterHierarchy
template
<
class TList,
class Unit,
class Root = EmptyType
>
class GenLinearHierarchy;
namespace Private
{
template <typename TListTag>
struct GenLinearHierarchyHelper
{
template<class TList, class Unit, class Root>
struct In
{
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::Private::Typelist_tag>
{
template<class TList, class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
typedef ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::Private::NullType_tag>
{
template<class TList, class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
public:
typedef ApplyInnerType2<Unit,Head, Root>::type Result;
};
};
template <class T, class U, class Root>
struct Wrap
{
struct Dummy {};
typedef typename T::Tail Tail;
// create the hierarchy
typedef typename Private::GenLinearHierarchyHelper
<
typename TL::Private::IsTypelist<Tail>::type_tag
>
::template In<T, U, Root>::Result TempType;
typedef typename
Private::VC_Base_Workaround<TempType, Dummy> type;
// this is nothing more than a typedef to the created hierarchy (TempType).
// But if we try to inherit directly from TempType VC 6.0
// will produce a "Error C2516. : is not a legal base class."
typedef type::LeftBase Base;
};
} // namespace Private
// Trying to inherit from LinBase will result in "Error C2516. : is not a legal base class."
// Private::Wrap introduces some levels of indirections which will
// make the vc happy.
template
<
class TList,
class Unit,
class Root
>
class GenLinearHierarchy : public Private::Wrap<TList, Unit, Root>::Base
{
ASSERT_TYPELIST(TList); // TList must not be NullType
public:
typedef typename Private::GenLinearHierarchyHelper
<
typename TL::Private::IsTypelist<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!!!
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6
////////////////////////////////////////////////////////////////////////////////
#undef IS_TYPELIST
#endif // HIERARCHYGENERATORS_INC_

157
MSVC/1200/MSVC6Helpers.h Normal file
View file

@ -0,0 +1,157 @@
#ifndef MSVC6HELPERS__H
#define MSVC6HELPERS__H
#if !defined (_MSC_VER) || _MSC_VER >= 1300
#error "please use this header only with MSVC 6.0"
#endif
namespace Loki
{
namespace Private
{
// workaround for the "Error C2516. : is not a legal base class"
// Use VC_Base_Workaround's LeftBase instead of the
// alleged illegal base class.
template <class T, class U>
struct VC_Base_Workaround : public T, public U
{
typedef T LeftBase;
};
// MSVC 6.0 does not allow the return of
// expressions of type "cv void" in a functions with a return
// type of cv void (6.6.3).
// Functor.h uses this Type as a workaround.
struct VoidAsType {};
// workarounds for template template parameters
////////////////////////////////////////////////////////////////////////////////
// class template AlwaysFalse
// Invocation: AlwaysFalse<T>::value
// value will always by 0 (false)
////////////////////////////////////////////////////////////////////////////////
template< typename T >
struct AlwaysFalse
{
enum { value = false };
};
////////////////////////////////////////////////////////////////////////////////
// class template ApplyImpl1
// Invocation: ApplyImpl1<T>::template Result<T1>
// T must be a nontemplate type with a nested class template named In.
// The class template is a helper for the Apply1-Template
////////////////////////////////////////////////////////////////////////////////
template <class TypeWithNestedTemplate>
struct ApplyImpl1
{
template<bool flag>
struct VC_WORKAROUND : public TypeWithNestedTemplate {};
struct VC_WORKAROUND<true>
{ template<class> struct In; };
template< typename T1 > struct Result : public
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1>
{
typedef VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template ApplyImpl2
// Invocation: ApplyImpl2<T>::template Result<T1, T2>
// T must be a nontemplate type with a nested class template named In.
// The class template is a helper for the Apply2-Template
////////////////////////////////////////////////////////////////////////////////
template <class TypeWithNestedTemplate>
struct ApplyImpl2
{
template<bool flag>
struct VC_WORKAROUND : public TypeWithNestedTemplate {};
struct VC_WORKAROUND<true>
{template<class T, class U> struct In; };
template< typename T1, typename T2 > struct Result : public
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2>
{
};
};
} // end of namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template Apply1
// Invocation: Apply1<T, U>
// Applies the type U to the inner template In of type T
// The class template Apply1 helps to emulate template template parameters
// i first saw this technique in boost's mpl library.
////////////////////////////////////////////////////////////////////////////////
template<typename F, typename T1>
struct Apply1 : Private::ApplyImpl1<F>::template Result<T1>
{
typedef typename Private::ApplyImpl1<F>::template Result<T1>::Base Base;
};
////////////////////////////////////////////////////////////////////////////////
// class template Apply2
// Invocation: Apply2<T, U, V>
// Applies the types U and V to the inner template In of type T
// The class template Apply2 helps to emulate template template parameters
// i first saw this technique in boost's mpl library.
////////////////////////////////////////////////////////////////////////////////
template<typename F, typename T1, typename T2>
struct Apply2 : Private::ApplyImpl2<F>::template Result<T1, T2>
{
};
////////////////////////////////////////////////////////////////////////////////
// class template ApplyInnerType
// Invocation: ApplyInnerType<Wrapper, U>::type
// Applies the type U to the the inner template 'In' of type Wrapper and typedefs
// the resulting type to 'type'
// The class template ApplyInnerType helps to emulate template template parameters
// i first saw this technique in boost's mpl library.
////////////////////////////////////////////////////////////////////////////////
template <class Wrapper, class T>
struct ApplyInnerType
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class X> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
};
////////////////////////////////////////////////////////////////////////////////
// class template ApplyInnerType2
// Invocation: ApplyInnerType2<Wrapper, U, V>::type
// Applies the types U and V to the the inner template 'In' of type Wrapper and typedefs
// the resulting type to 'type'
// The class template ApplyInnerType helps to emulate template template parameters
// i first saw this technique in boost's mpl library.
////////////////////////////////////////////////////////////////////////////////
template <class Wrapper, class T, class V>
struct ApplyInnerType2
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class X, class Y> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
};
template <class Wrapper, class T, class U, class V, class W>
struct ApplyInnerType4
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class W, class X, class Y, class Z> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
};
}
#endif

466
MSVC/1200/MultiMethods.h Normal file
View file

@ -0,0 +1,466 @@
////////////////////////////////////////////////////////////////////////////////
// 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: Oct 28, 2002
// Because MSVC 6.0 does not allow a functions with a return
// type of cv void to return an expression of type "cv void" (6.6.3), this
// port currently *does not* support void as return type.
//
// Because the VC 6.0 does not support explicit template argument specification
// for member functions (14.8.1), I added dummy parameters to functions
// requiring this feature.
// For example:
// The original declaration of BasicDispatcher::Add looks like this:
//
// template <class SomeLhs, class SomeRhs>
// void Add(CallbackType fun);
// and you call it like this:
// obj.Add<Type1, Type2>(yourFun);
//
// This port uses:
//
// template <class SomeLhs, class SomeRhs>
// void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2);
//
// and you call it like this:
// obj.Add(yourFun, (Type1*)0, (Type2*)0);
#ifndef MULTIMETHODS_INC_
#define MULTIMETHODS_INC_
#include "Typelist.h"
#include "TypeInfo.h"
#include "Functor.h"
#include "AssocVector.h"
////////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE:
// The double dispatchers implemented below differ from the excerpts shown in
// the book - they are simpler while respecting the same interface.
////////////////////////////////////////////////////////////////////////////////
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template InvocationTraits (helper)
// Helps implementing optional symmetry
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class SomeLhs, class SomeRhs,
class Executor, typename ResultType>
struct InvocationTraits
{
static ResultType
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
{
return exec.Fire(lhs, rhs);
}
static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs,
Executor& exec, Int2Type<true>)
{
return exec.Fire(rhs, lhs);
}
};
}
////////////////////////////////////////////////////////////////////////////////
// class template StaticDispatcher
// Implements an automatic static double dispatcher based on two typelists
////////////////////////////////////////////////////////////////////////////////
template
<
class Executor,
class BaseLhs,
class TypesLhs,
bool symmetric = true,
class BaseRhs = BaseLhs,
class TypesRhs = TypesLhs,
typename ResultType = int/*void*/
>
class StaticDispatcher
{
template <class SomeLhs>
static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs,
Executor exec, NullType)
{ return exec.OnError(lhs, rhs); }
template <class Head, class Tail, class SomeLhs>
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
Executor exec, Typelist<Head, Tail>)
{
if (Head* p2 = dynamic_cast<Head*>(&rhs))
{
Int2Type<(symmetric &&
int(TL::IndexOf<TypesRhs, Head>::value) <
int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t;
typedef Private::InvocationTraits<
SomeLhs, Head, Executor, ResultType> CallTraits;
return CallTraits::DoDispatch(lhs, *p2, exec, i2t);
}
return DispatchRhs(lhs, rhs, exec, Tail());
}
static ResultType DispatchLhs( BaseLhs& lhs, BaseRhs& rhs,
Executor exec, NullType)
{ return exec.OnError(lhs, rhs); }
template <class Head, class Tail>
static ResultType DispatchLhs( BaseLhs& lhs, BaseRhs& rhs,
Executor exec, Typelist<Head, Tail>)
{
if (Head* p1 = dynamic_cast<Head*>(&lhs))
{
return DispatchRhs(*p1, rhs, exec, TypesRhs());
}
return DispatchLhs(lhs, rhs, exec, Tail());
}
public:
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
Executor exec)
{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
};
////////////////////////////////////////////////////////////////////////////////
// class template BasicDispatcher
// Implements a logarithmic double dispatcher for functors (or functions)
// Doesn't offer automated casts or symmetry
////////////////////////////////////////////////////////////////////////////////
template
<
class BaseLhs,
class BaseRhs = BaseLhs,
typename ResultType = int/*void*/,
typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
>
class BasicDispatcher
{
typedef std::pair<TypeInfo,TypeInfo> KeyType;
typedef CallbackType MappedType;
typedef AssocVector<KeyType, MappedType> MapType;
MapType callbackMap_;
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);
bool DoRemove(TypeInfo lhs, TypeInfo rhs);
public:
template <class SomeLhs, class SomeRhs>
void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2)
{
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
}
template <class SomeLhs, class SomeRhs>
bool Remove(SomeLhs pDummy1, SomeRhs pDummy2)
{
return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
}
ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
};
// Non-inline to reduce compile time overhead...
template <class BaseLhs, class BaseRhs,
typename ResultType, typename CallbackType>
void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
{
callbackMap_[KeyType(lhs, rhs)] = fun;
}
template <class BaseLhs, class BaseRhs,
typename ResultType, typename CallbackType>
bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
::DoRemove(TypeInfo lhs, TypeInfo rhs)
{
return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
}
template <class BaseLhs, class BaseRhs,
typename ResultType, typename CallbackType>
ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
::Go(BaseLhs& lhs, BaseRhs& rhs)
{
typename MapType::key_type k(typeid(lhs),typeid(rhs));
typename MapType::iterator i = callbackMap_.find(k);
if (i == callbackMap_.end())
{
throw std::runtime_error("Function not found");
}
return (i->second)(lhs, rhs);
}
struct BasicDispatcherWrapper
{
template <class T, class U, class V, class W>
struct In
{
typedef BasicDispatcher<T, U, V, W> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template StaticCaster
// Implementation of the CastingPolicy used by FunctorDispatcher
////////////////////////////////////////////////////////////////////////////////
template <class To, class From>
struct StaticCaster
{
static To& Cast(From& obj)
{
return static_cast<To&>(obj);
}
};
struct StaticCasterWrapper
{
template <class T, class U>
struct In
{
typedef StaticCaster<T, U> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template DynamicCaster
// Implementation of the CastingPolicy used by FunctorDispatcher
////////////////////////////////////////////////////////////////////////////////
template <class To, class From>
struct DynamicCaster
{
static To& Cast(From& obj)
{
return dynamic_cast<To&>(obj);
}
};
struct DynamicCasterWrapper
{
template <class T, class U>
struct In
{
typedef DynamicCaster<T, U> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template Private::FnDispatcherHelper
// Implements trampolines and argument swapping used by FnDispatcher
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template
<
class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
typename ResultType, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&)
>
struct FnDispatcherHelper
{
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{
return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{
return Trampoline(lhs, rhs);
}
};
}
////////////////////////////////////////////////////////////////////////////////
// class template FnDispatcher
// Implements an automatic logarithmic double dispatcher for functions
// Features automated conversions
////////////////////////////////////////////////////////////////////////////////
template <class BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = int/*void*/,
class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper>
class FnDispatcher
{
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
public:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&), SomeLhs* pDummy1, SomeRhs* pDummy2)
{
return backEnd_.Add(pFun, pDummy1, pDummy2);
}
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add(SomeLhs* pDummy1, SomeRhs* pDummy2)
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
typename ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local;
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0);
}
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add(SomeLhs* pDummy1, SomeRhs* pDummy2, bool Symmetric)
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
typename ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local;
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0);
if (Symmetric)
{
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0);
}
}
template <class SomeLhs, class SomeRhs>
void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2)
{
backEnd_.Remove(pDummy1, pDummy2);
}
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return backEnd_.Go(lhs, rhs);
}
};
////////////////////////////////////////////////////////////////////////////////
// class template FunctorDispatcherAdaptor
// permits use of FunctorDispatcher under gcc.2.95.2/3
///////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class BaseLhs, class BaseRhs,
class SomeLhs, class SomeRhs,
typename ResultType,
class CastLhs, class CastRhs,
class Fun, bool SwapArgs>
class FunctorDispatcherHelper
{
Fun fun_;
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
{
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
{
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
public:
FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{
return Fire(lhs,rhs,Int2Type<SwapArgs>());
}
};
}
////////////////////////////////////////////////////////////////////////////////
// class template FunctorDispatcher
// Implements a logarithmic double dispatcher for functors
// Features automated casting
////////////////////////////////////////////////////////////////////////////////
template <class BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = int/*void*/,
class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper>
class FunctorDispatcher
{
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType, FunctorType>::type backEnd_;
public:
template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2)
{
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseRhs>::type CastTwo;
typedef Private::FunctorDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
CastOne,
CastTwo,
Fun, false> Adapter;
backEnd_.Add(FunctorType(Adapter(fun), (int*) 0), pDummy1, pDummy2);
}
template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2, bool symmetric)
{
Add(fun, pDummy1, pDummy2);
if (symmetric)
{
// Note: symmetry only makes sense where BaseLhs==BaseRhs
typedef Private::FunctorDispatcherHelper<
BaseLhs, BaseLhs,
SomeLhs, SomeRhs,
ResultType,
ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type,
ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type,
Fun, true> AdapterR;
backEnd_.Add(FunctorType(Adapter(fun)), pDummy1, pDummy2);
}
}
template <class SomeLhs, class SomeRhs>
void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2)
{
backEnd_.Remove(pDummy1, pDummy2);
}
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return backEnd_.Go(lhs, rhs);
}
};
} // 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)
// Oct 28, 2002: ported by Benjamin Kaufmann
////////////////////////////////////////////////////////////////////////////////
#endif

37
MSVC/1200/NullType.h Normal file
View file

@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////////
// 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: June 20, 2001
#ifndef NULLTYPE_INC_
#define NULLTYPE_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class NullType
// Used as a placeholder for "no type here"
// Useful as an end marker in typelists
////////////////////////////////////////////////////////////////////////////////
class NullType {};
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif // NULLTYPE_INC_

239
MSVC/1200/Readme.txt Normal file
View file

@ -0,0 +1,239 @@
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
-------------------------------------------------------------------
Introduction/Compatibility:
---------------------------
This is a partial MSVC 6.0 Sp5 compatible port of Andrei Alexandrescu's excellent Loki Library.
Because I could not retain the originial interface in all places, this port is not
compatible to the original library and therefore code using this port *cannot* generally be
used together with the original lib.
This is, of course, a great pity.
So if you know of a complete and full interface-compatible VC 6.0
port or if you know how to improve this port, please let me know.
Contact:
--------
For any suggestions, bug reports, comments and questions please email me to
Hume@c-plusplus.de
Using this port:
----------------
To use this port, simply extract the files from the archive, give your compiler access to
their path, and include them appropriately in your code via #include.
If you use the small object allocator directly or indirectly (through the Functor class)
you must add SmallObj.cpp to your project/makefile.
If you use Singletons with longevity you must add Singleton.cpp to your project/makefile.
Notes:
------
The original Loki Lib uses some pretty advanced (resp. new) C++ features like:
A. partial template specialization.
B. template template parameters.
C. explicit template argument specification for member- and nonmeber functions.
D. covariant return types.
E. Template parameters with a default type void
F. return statements with an expression of type cv in functions with a return type of cv void.
G. Template-ctor resp. template assignment operator
Unfortunately the MSVC 6.0 supports neither of them.
A. I used various techniques to simulate partial template specialization. In some cases
these techniques allowed me to retain the original interfaces but often that was not
possible (or better: i did not find a proper solution). In any case it leads
to increasing code complexity :-)
B. One way to simulate template template parameters is to replace the template class with
a normal class containing a nested template class. You then move the original functionality
to the nested class.
The problem with this approach is MSVC's 'dependent template typedef bug'. MSVC 6.0 does not
allow something like this:
[code]
template <class APolicy, class T>
struct Foo
{
// 'error C1001 - Internal Compiler Error' here
typedef typename APolicy::template In<T> type;
};
[/code]
To make a long story short, I finally decided to use boost::mpl's apply-technique to
simulate template template parameters. This approach works fine with MSVC 6.0. But be warned,
this technique uses not valid C++.
Of course, replacing template template parameters always results in some interface changes.
C. I added dummy-Parameters to (Member-)Functions that depend on explicit template
argument specification. These dummy-Parameters help the compiler in deducing the template
parameters that otherwise need to be explicitly specified.
Example:
[code]
struct Foo
{
template <class T>
T Func();
};
[/code]
becomes
[code]
struct Foo
{
template <class T>
T Func(T* pDummy1);
};
[/code]
in this port.
D. Virtual functions that use covariant return types (e.g. return a pointer to Derived)
in the original library were changed so that they have exactly the
same return type as the original virtual function (e.g. return a pointer to Base).
E. All template parameters that have a default type of void in the original lib now
have int as default type.
F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent
for the user of Functor.
Because I could not think of any general and transparent workaround I followed different
strategies. In Visitor.h for example I created new classes (and macros) for the void-case.
In other places (for example: MultiMethod.h) this port simply fails to support void as
return type :-(
G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version
is present. On the other hand the MSVC 6.0 allows explicit template specialization in class
scope. I used this "feature" as a workaround for code like this:
[code]
template <class T>
struct Foo
{
Foo(const Foo&);
template <class U>
Foo(const Foo<U>&);
};
[/code]
Under MSVC 6.0 the above code becomes:
[code]
template <class T>
struct Foo
{
template <class U>
Foo(const Foo<U>&);
// copy-ctor for Foos with equal T
// not valid c++
template <>
Foo(const Foo&);
};
[/code]
Interface changes:
------------------
1. In Threads.h:
* Thread-Policies changed from class templates to normal classes containing a
nested class template 'In'.
consequences:
This change is not very dramatic because it won't break code using this port when
switching to the original library (only new Thread-Policies must be changed)
2. In Singleton.h:
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
Member-Templates.
consequences:
Again this change will only break new Policies when switching to the
original library.
3. In Functor.h:
* No covariant return types.
consequences:
DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return
type and ThreadingModel its current ThreadingModel.
4. TypeTraits.h
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class provides not
all the stuff provided by the original library's version.
5. HierarchyGenerator.h
* I used Mat Marcus' approach to port GenScatterHierarchy.
See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences.
* Same for GenLinearHierarchy
* Unit is no longer a template template parameter.
consequences:
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.
6. Factory.h
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter.
Use a class with member-templates instead.
consequences:
This change will only break new Policies when switching to the
original library.
7. AbstractFactory.h
* no covariant return types
* no template template parameters
For every concrete Factory-Unit there must be a normal class containing
a nested-template class called 'In'. 'In' shall contain a typedef to the
concrete Factory-Unit.
* Added a dummy-Parameter to AbstractFactory::Create (see C.)
Calling syntax changed from:
ConcProduct* p = aFactory.Create<ConcProduct>();
to
ConcProduct* p = aFactory.Create((ConcProduct*)0);
8. SmartPtr.h
* no template template parameters.
(see 7.for a description of the consequences)
* This port does not specialize std::less
9. Visitor.h
* no template template parameters
(see 7.for a description of the consequences)
* This port fails to correctly support void return types. As a workaround it provides
a set of complete new classes (and macros) for void. Default arguments of type void
were replaced by arguments of type int.
10. MultiMethods.h
* replaced all template template parameters with 'normal' parameters (see 7.
for a description of the consequences)
* This port does not support functions with return type void.
* dummy parameters were added to functions that otherwise would depend on
explicit template argument specification (14.8.1).
More info:
----------
The original Loki library can be found here: http://moderncppdesign.com
For Rani Sharoni's VC 7.0 port see: http://www.geocities.com/rani_sharoni/LokiPort.html

49
MSVC/1200/Singleton.cpp Normal file
View file

@ -0,0 +1,49 @@
////////////////////////////////////////////////////////////////////////////////
// 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: Oct 06, 2002
#include "Singleton.h"
using namespace Loki::Private;
Loki::Private::TrackerArray Loki::Private::pTrackerArray = 0;
unsigned int Loki::Private::elements = 0;
////////////////////////////////////////////////////////////////////////////////
// function AtExitFn
// Ensures proper destruction of objects with longevity
////////////////////////////////////////////////////////////////////////////////
void Loki::Private::AtExitFn()
{
assert(elements > 0 && pTrackerArray != 0);
// Pick the element at the top of the stack
LifetimeTracker* pTop = pTrackerArray[elements - 1];
// Remove that object off the stack
// Don't check errors - realloc with less memory
// can't fail
pTrackerArray = static_cast<TrackerArray>(VC_BROKEN_STD::realloc(
pTrackerArray, sizeof(*pTrackerArray) * --elements));
// Destroy the element
delete pTop;
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Oct 06 2002: ported by Benjamin Kaufmann to VC 6.0
////////////////////////////////////////////////////////////////////////////////

480
MSVC/1200/Singleton.h Normal file
View file

@ -0,0 +1,480 @@
////////////////////////////////////////////////////////////////////////////////
// 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: Oct 07, 2002
#ifndef SINGLETON_INC_
#define SINGLETON_INC_
#include "Threads.h"
#include "MSVC6Helpers.h" // for apply-template
#include <algorithm>
#include <stdexcept>
#include <cassert>
#include <cstdlib>
#include <new>
#if _MSC_VER <= 1200
#define VC_BROKEN_STD
#else
#define VC_BROKEN_STD std
#endif
namespace Loki
{
namespace Private
{
////////////////////////////////////////////////////////////////////////////////
// class LifetimeTracker
// Helper class for SetLongevity
////////////////////////////////////////////////////////////////////////////////
class LifetimeTracker
{
public:
LifetimeTracker(unsigned int x) : longevity_(x)
{}
virtual ~LifetimeTracker() = 0;
static bool Compare(const LifetimeTracker* lhs,
const LifetimeTracker* rhs)
{
return rhs->longevity_ > lhs->longevity_;
}
private:
unsigned int longevity_;
};
// Definition required
inline LifetimeTracker::~LifetimeTracker() {}
// Helper data
typedef LifetimeTracker** TrackerArray;
extern TrackerArray pTrackerArray;
extern unsigned int elements;
// Helper destroyer function
template <typename T>
struct Deleter
{
static void Delete(T* pObj)
{ delete pObj; }
};
// Concrete lifetime tracker for objects of type T
template <typename T, typename Destroyer>
class ConcreteLifetimeTracker : public LifetimeTracker
{
public:
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
: LifetimeTracker(longevity)
, pTracked_(p)
, destroyer_(d)
{}
~ConcreteLifetimeTracker()
{ destroyer_(pTracked_); }
private:
T* pTracked_;
Destroyer destroyer_;
};
void AtExitFn(); // declaration needed below
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// function template SetLongevity
// Assigns an object a longevity; ensures ordered destructions of objects
// registered thusly during the exit sequence of the application
////////////////////////////////////////////////////////////////////////////////
template <typename T, typename Destroyer>
void SetLongevity(T* pDynObject, unsigned int longevity,
Destroyer d = Private::Deleter<T>::Delete)
{
using namespace Private;
TrackerArray pNewArray = static_cast<TrackerArray>(
VC_BROKEN_STD::realloc(pTrackerArray, sizeof(*pTrackerArray) * (elements + 1)));
if (!pNewArray) throw std::bad_alloc();
// Delayed assignment for exception safety
pTrackerArray = pNewArray;
LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
pDynObject, longevity, d);
// Insert a pointer to the object into the queue
TrackerArray pos = std::upper_bound(
pTrackerArray,
pTrackerArray + elements,
p,
LifetimeTracker::Compare);
std::copy_backward(
pos,
pTrackerArray + elements,
pTrackerArray + elements + 1);
*pos = p;
++elements;
// Register a call to AtExitFn
VC_BROKEN_STD::atexit(Private::AtExitFn);
}
////////////////////////////////////////////////////////////////////////////////
// class template CreateUsingNew
// Implementation of the CreationPolicy used by SingletonHolder
// Creates objects using a straight call to the new operator
////////////////////////////////////////////////////////////////////////////////
struct CreateUsingNew
{
template <class T>
static T* Create(const volatile T* p = 0)
{
return new T;
}
template <class T>
static void Destroy(T* p)
{ delete p; }
};
////////////////////////////////////////////////////////////////////////////////
// class template CreateUsingNew
// Implementation of the CreationPolicy used by SingletonHolder
// Creates objects using a call to std::malloc, followed by a call to the
// placement new operator
////////////////////////////////////////////////////////////////////////////////
struct CreateUsingMalloc
{
template <class T>
static T* Create(const volatile T* p = 0)
{
void* p = VC_BROKEN_STD::malloc(sizeof(T));
if (!p) return 0;
return new(p) T;
}
template <class T>
static void Destroy(T* p)
{
p->~T();
VC_BROKEN_STD::free(p);
}
};
////////////////////////////////////////////////////////////////////////////////
// class template CreateStatic
// Implementation of the CreationPolicy used by SingletonHolder
// Creates an object in static memory
// Implementation is slightly nonportable because it uses the MaxAlign trick
// (an union of all types to ensure proper memory alignment). This trick is
// nonportable in theory but highly portable in practice.
////////////////////////////////////////////////////////////////////////////////
struct CreateStatic
{
#ifdef _MSC_VER
#pragma warning( push )
// alignment of a member was sensitive to packing
#pragma warning( disable : 4121 )
#endif // _MSC_VER
template <class T>
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
#ifdef _MSC_VER
#pragma warning( pop )
#endif // _MSC_VER
template <class T>
static T* Create(const volatile T* p = 0)
{
static MaxAlign<T> staticMemory_;
return new(&staticMemory_) T;
}
template <class T>
static void Destroy(T* p)
{
p->~T();
}
};
////////////////////////////////////////////////////////////////////////////////
// class template DefaultLifetime
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction as per C++ rules
// Forwards to std::atexit
////////////////////////////////////////////////////////////////////////////////
struct DefaultLifetime
{
template <class T>
static void ScheduleDestruction(T*, void (*pFun)())
{ VC_BROKEN_STD::atexit(pFun); }
template <class T>
static void OnDeadReference(const volatile T* p = 0 )
{ throw std::logic_error("Dead Reference Detected"); }
};
////////////////////////////////////////////////////////////////////////////////
// class template PhoenixSingleton
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction as per C++ rules, and it allows object
// recreation by not throwing an exception from OnDeadReference
////////////////////////////////////////////////////////////////////////////////
class PhoenixSingleton
{
private:
template <class T>
struct StaticData
{
static bool destroyedOnce_;
};
public:
template <class T>
static void ScheduleDestruction(T*, void (*pFun)())
{
#ifndef ATEXIT_FIXED
if (!StaticData<T>::destroyedOnce_)
#endif
VC_BROKEN_STD::atexit(pFun);
}
template <class T>
static void OnDeadReference(const volatile T* p = 0 )
{
#ifndef ATEXIT_FIXED
StaticData<T>::destroyedOnce_ = true;
#endif
}
};
#ifndef ATEXIT_FIXED
template <class T>
bool ::Loki::PhoenixSingleton::StaticData<T>::destroyedOnce_ = false;
#endif
////////////////////////////////////////////////////////////////////////////////
// class template Adapter
// Helper for SingletonWithLongevity below
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class T>
struct Adapter
{
void operator()(T*) { pFun_(); return ; }
void (*pFun_)();
};
}
////////////////////////////////////////////////////////////////////////////////
// class template SingletonWithLongevity
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction in order of their longevities
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
// object
////////////////////////////////////////////////////////////////////////////////
class SingletonWithLongevity
{
public:
template <class T>
static void ScheduleDestruction(T* pObj, void (*pFun)())
{
Private::Adapter<T> adapter;
adapter.pFun_ = pFun ;
SetLongevity(pObj, GetLongevity(pObj), adapter);
}
template <class T>
static void OnDeadReference(const volatile T* p = 0 )
{ throw std::logic_error("Dead Reference Detected"); }
};
////////////////////////////////////////////////////////////////////////////////
// class template NoDestroy
// Implementation of the LifetimePolicy used by SingletonHolder
// Never destroys the object
////////////////////////////////////////////////////////////////////////////////
struct NoDestroy
{
template <class T>
static void ScheduleDestruction(T*, void (*)())
{}
template <class T>
static void OnDeadReference(const volatile T* p = 0)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template SingletonHolder
// Provides Singleton amenities for a type T
// To protect that type from spurious instantiations, you have to protect it
// yourself.
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
class CreationPolicy = CreateUsingNew,
class LifetimePolicy = DefaultLifetime,
class ThreadingModel = SingleThreaded
>
class SingletonHolder
{
public:
static T& Instance();
private:
// Helpers
static void MakeInstance();
static void DestroySingleton();
// Protection
SingletonHolder();
// Data
typedef typename Apply1<ThreadingModel, T*>::VolatileType VolatileType;
static VolatileType pInstance_;
static bool destroyed_;
};
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder's data
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class C,
class L,
class M
>
typename SingletonHolder<T, C, L, M>::VolatileType
SingletonHolder<T, C, L, M>::pInstance_;
template
<
class T,
class C,
class L,
class M
>
bool SingletonHolder<T, C, L, M>::destroyed_;
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder::Instance
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class CreationPolicy,
class LifetimePolicy,
class ThreadingModel
>
inline T& SingletonHolder<T, CreationPolicy,
LifetimePolicy, ThreadingModel>::Instance()
{
if (!pInstance_)
{
MakeInstance();
}
return *pInstance_;
}
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder::MakeInstance (helper for Instance)
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class CreationPolicy,
class LifetimePolicy,
class ThreadingModel
>
void SingletonHolder<T, CreationPolicy,
LifetimePolicy, ThreadingModel>::MakeInstance()
{
typename Apply1<ThreadingModel, T>::Lock guard;
(void)guard;
if (!pInstance_)
{
if (destroyed_)
{
LifetimePolicy::OnDeadReference(pInstance_);
destroyed_ = false;
}
pInstance_ = CreationPolicy::Create(pInstance_);
LifetimePolicy::ScheduleDestruction(pInstance_,
&DestroySingleton);
}
}
template
<
class T,
class CreationPolicy,
class L,
class M
>
void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
{
assert(!destroyed_);
CreationPolicy::Destroy(pInstance_);
pInstance_ = 0;
destroyed_ = true;
}
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Oct 06 2002: ported by Benjamin Kaufmann to MSVC 6.0
////////////////////////////////////////////////////////////////////////////////
#endif // SINGLETON_INC_

420
MSVC/1200/SmallObj.cpp Normal file
View file

@ -0,0 +1,420 @@
////////////////////////////////////////////////////////////////////////////////
// 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: March 20, 2001
#include "SmallObj.h"
#include <cassert>
#include <algorithm>
using namespace Loki;
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Init
// Initializes a chunk object
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Chunk::Init(VC_BROKEN_STD::size_t blockSize, unsigned char blocks)
{
assert(blockSize > 0);
assert(blocks > 0);
// Overflow check
assert((blockSize * blocks) / blockSize == blocks);
pData_ = new unsigned char[blockSize * blocks];
Reset(blockSize, blocks);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Reset
// Clears an already allocated chunk
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Chunk::Reset(VC_BROKEN_STD::size_t blockSize, unsigned char blocks)
{
assert(blockSize > 0);
assert(blocks > 0);
// Overflow check
assert((blockSize * blocks) / blockSize == blocks);
firstAvailableBlock_ = 0;
blocksAvailable_ = blocks;
unsigned char i = 0;
unsigned char* p = pData_;
for (; i != blocks; p += blockSize)
{
*p = ++i;
}
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Release
// Releases the data managed by a chunk
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Chunk::Release()
{
delete[] pData_;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Allocate
// Allocates a block from a chunk
////////////////////////////////////////////////////////////////////////////////
void* FixedAllocator::Chunk::Allocate(VC_BROKEN_STD::size_t blockSize)
{
if (!blocksAvailable_) return 0;
assert((firstAvailableBlock_ * blockSize) / blockSize ==
firstAvailableBlock_);
unsigned char* pResult =
pData_ + (firstAvailableBlock_ * blockSize);
firstAvailableBlock_ = *pResult;
--blocksAvailable_;
return pResult;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Deallocate
// Dellocates a block from a chunk
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Chunk::Deallocate(void* p, VC_BROKEN_STD::size_t blockSize)
{
assert(p >= pData_);
unsigned char* toRelease = static_cast<unsigned char*>(p);
// Alignment check
assert((toRelease - pData_) % blockSize == 0);
*toRelease = firstAvailableBlock_;
firstAvailableBlock_ = static_cast<unsigned char>(
(toRelease - pData_) / blockSize);
// Truncation check
assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);
++blocksAvailable_;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::FixedAllocator
// Creates a FixedAllocator object of a fixed block size
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::FixedAllocator(VC_BROKEN_STD::size_t blockSize)
: blockSize_(blockSize)
, allocChunk_(0)
, deallocChunk_(0)
{
assert(blockSize_ > 0);
prev_ = next_ = this;
VC_BROKEN_STD::size_t numBlocks = DEFAULT_CHUNK_SIZE / blockSize;
if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX;
else if (numBlocks == 0) numBlocks = 8 * blockSize;
numBlocks_ = static_cast<unsigned char>(numBlocks);
assert(numBlocks_ == numBlocks);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::FixedAllocator(const FixedAllocator&)
// Creates a FixedAllocator object of a fixed block size
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::FixedAllocator(const FixedAllocator& rhs)
: blockSize_(rhs.blockSize_)
, numBlocks_(rhs.numBlocks_)
, chunks_(rhs.chunks_)
{
prev_ = &rhs;
next_ = rhs.next_;
rhs.next_->prev_ = this;
rhs.next_ = this;
allocChunk_ = rhs.allocChunk_
? &chunks_.front() + (rhs.allocChunk_ - &rhs.chunks_.front())
: 0;
deallocChunk_ = rhs.deallocChunk_
? &chunks_.front() + (rhs.deallocChunk_ - &rhs.chunks_.front())
: 0;
}
FixedAllocator& FixedAllocator::operator=(const FixedAllocator& rhs)
{
FixedAllocator copy(rhs);
copy.Swap(*this);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::~FixedAllocator
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::~FixedAllocator()
{
if (prev_ != this)
{
prev_->next_ = next_;
next_->prev_ = prev_;
return;
}
assert(prev_ == next_);
Chunks::iterator i = chunks_.begin();
for (; i != chunks_.end(); ++i)
{
assert(i->blocksAvailable_ == numBlocks_);
i->Release();
}
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Swap
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Swap(FixedAllocator& rhs)
{
using namespace std;
swap(blockSize_, rhs.blockSize_);
swap(numBlocks_, rhs.numBlocks_);
chunks_.swap(rhs.chunks_);
swap(allocChunk_, rhs.allocChunk_);
swap(deallocChunk_, rhs.deallocChunk_);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Allocate
// Allocates a block of fixed size
////////////////////////////////////////////////////////////////////////////////
void* FixedAllocator::Allocate()
{
if (allocChunk_ == 0 || allocChunk_->blocksAvailable_ == 0)
{
Chunks::iterator i = chunks_.begin();
for (;; ++i)
{
if (i == chunks_.end())
{
// Initialize
chunks_.reserve(chunks_.size() + 1);
Chunk newChunk;
newChunk.Init(blockSize_, numBlocks_);
chunks_.push_back(newChunk);
allocChunk_ = &chunks_.back();
deallocChunk_ = &chunks_.front();
break;
}
if (i->blocksAvailable_ > 0)
{
allocChunk_ = &*i;
break;
}
}
}
assert(allocChunk_ != 0);
assert(allocChunk_->blocksAvailable_ > 0);
return allocChunk_->Allocate(blockSize_);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Deallocate
// Deallocates a block previously allocated with Allocate
// (undefined behavior if called with the wrong pointer)
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Deallocate(void* p)
{
assert(!chunks_.empty());
assert(&chunks_.front() <= deallocChunk_);
assert(&chunks_.back() >= deallocChunk_);
deallocChunk_ = VicinityFind(p);
assert(deallocChunk_);
DoDeallocate(p);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::VicinityFind (internal)
// Finds the chunk corresponding to a pointer, using an efficient search
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p)
{
assert(!chunks_.empty());
assert(deallocChunk_);
const VC_BROKEN_STD::size_t chunkLength = numBlocks_ * blockSize_;
Chunk* lo = deallocChunk_;
Chunk* hi = deallocChunk_ + 1;
Chunk* loBound = &chunks_.front();
Chunk* hiBound = &chunks_.back() + 1;
// Special case: deallocChunk_ is the last in the array
if (hi == hiBound) hi = 0;
for (;;)
{
if (lo)
{
if (p >= lo->pData_ && p < lo->pData_ + chunkLength)
{
return lo;
}
if (lo == loBound) lo = 0;
else --lo;
}
if (hi)
{
if (p >= hi->pData_ && p < hi->pData_ + chunkLength)
{
return hi;
}
if (++hi == hiBound) hi = 0;
}
}
assert(false);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::DoDeallocate (internal)
// Performs deallocation. Assumes deallocChunk_ points to the correct chunk
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::DoDeallocate(void* p)
{
assert(deallocChunk_->pData_ <= p);
assert(deallocChunk_->pData_ + numBlocks_ * blockSize_ > p);
// call into the chunk, will adjust the inner list but won't release memory
deallocChunk_->Deallocate(p, blockSize_);
if (deallocChunk_->blocksAvailable_ == numBlocks_)
{
// deallocChunk_ is completely free, should we release it?
Chunk& lastChunk = chunks_.back();
if (&lastChunk == deallocChunk_)
{
// check if we have two last chunks empty
if (chunks_.size() > 1 &&
deallocChunk_[-1].blocksAvailable_ == numBlocks_)
{
// Two free chunks, discard the last one
lastChunk.Release();
chunks_.pop_back();
allocChunk_ = deallocChunk_ = &chunks_.front();
}
return;
}
if (lastChunk.blocksAvailable_ == numBlocks_)
{
// Two free blocks, discard one
lastChunk.Release();
chunks_.pop_back();
allocChunk_ = deallocChunk_;
}
else
{
// move the empty chunk to the end
std::swap(*deallocChunk_, lastChunk);
allocChunk_ = &chunks_.back();
}
}
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::SmallObjAllocator
// Creates an allocator for small objects given chunk size and maximum 'small'
// object size
////////////////////////////////////////////////////////////////////////////////
SmallObjAllocator::SmallObjAllocator(
VC_BROKEN_STD::size_t chunkSize,
VC_BROKEN_STD::size_t maxObjectSize)
: pLastAlloc_(0), pLastDealloc_(0)
, chunkSize_(chunkSize), maxObjectSize_(maxObjectSize)
{
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::Allocate
// Allocates 'numBytes' memory
// Uses an internal pool of FixedAllocator objects for small objects
////////////////////////////////////////////////////////////////////////////////
void* SmallObjAllocator::Allocate(VC_BROKEN_STD::size_t numBytes)
{
if (numBytes > maxObjectSize_) return operator new(numBytes);
if (pLastAlloc_ && pLastAlloc_->BlockSize() == numBytes)
{
return pLastAlloc_->Allocate();
}
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
if (i == pool_.end() || i->BlockSize() != numBytes)
{
i = pool_.insert(i, FixedAllocator(numBytes));
pLastDealloc_ = &*pool_.begin();
}
pLastAlloc_ = &*i;
return pLastAlloc_->Allocate();
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::Deallocate
// Deallocates memory previously allocated with Allocate
// (undefined behavior if you pass any other pointer)
////////////////////////////////////////////////////////////////////////////////
void SmallObjAllocator::Deallocate(void* p, VC_BROKEN_STD::size_t numBytes)
{
if (numBytes > maxObjectSize_) {operator delete(p); return;}
if (pLastDealloc_ && pLastDealloc_->BlockSize() == numBytes)
{
pLastDealloc_->Deallocate(p);
return;
}
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
assert(i != pool_.end());
assert(i->BlockSize() == numBytes);
pLastDealloc_ = &*i;
pLastDealloc_->Deallocate(p);
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// March 20: fix exception safety issue in FixedAllocator::Allocate
// (thanks to Chris Udazvinis for pointing that out)
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Aug 02, 2002: Fix in VicinityFind sent by Pavel Vozenilek
// Oct 11, 2002: ported by Benjamin Kaufmann to VC 6.0
////////////////////////////////////////////////////////////////////////////////

193
MSVC/1200/SmallObj.h Normal file
View file

@ -0,0 +1,193 @@
////////////////////////////////////////////////////////////////////////////////
// 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 11, 2002
#ifndef SMALLOBJ_INC_
#define SMALLOBJ_INC_
#include "Threads.h"
#include "Singleton.h"
#include "MSVC6Helpers.h" // for apply-template
#include <cstddef>
#include <vector>
#ifdef _MSC_VER
#define for if(0);else for
# pragma warning(disable:4291)
#endif
#ifndef DEFAULT_CHUNK_SIZE
#define DEFAULT_CHUNK_SIZE 4096
#endif
#ifndef MAX_SMALL_OBJECT_SIZE
#define MAX_SMALL_OBJECT_SIZE 64
#endif
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class FixedAllocator
// Offers services for allocating fixed-sized objects
////////////////////////////////////////////////////////////////////////////////
class FixedAllocator
{
public: // VC7 access control BUG
class Chunk
{
friend FixedAllocator;
void Init(VC_BROKEN_STD::size_t blockSize, unsigned char blocks);
void* Allocate(VC_BROKEN_STD::size_t blockSize);
void Deallocate(void* p, VC_BROKEN_STD::size_t blockSize);
void Reset(VC_BROKEN_STD::size_t blockSize, unsigned char blocks);
void Release();
unsigned char* pData_;
unsigned char
firstAvailableBlock_,
blocksAvailable_;
};
private:
// Internal functions
void DoDeallocate(void* p);
Chunk* VicinityFind(void* p);
// Data
VC_BROKEN_STD::size_t blockSize_;
unsigned char numBlocks_;
typedef std::vector<Chunk> Chunks;
Chunks chunks_;
Chunk* allocChunk_;
Chunk* deallocChunk_;
// For ensuring proper copy semantics
mutable const FixedAllocator* prev_;
mutable const FixedAllocator* next_;
public:
// Create a FixedAllocator able to manage blocks of 'blockSize' size
explicit FixedAllocator(VC_BROKEN_STD::size_t blockSize = 0);
FixedAllocator(const FixedAllocator&);
FixedAllocator& operator=(const FixedAllocator&);
~FixedAllocator();
void Swap(FixedAllocator& rhs);
// Allocate a memory block
void* Allocate();
// Deallocate a memory block previously allocated with Allocate()
// (if that's not the case, the behavior is undefined)
void Deallocate(void* p);
// Returns the block size with which the FixedAllocator was initialized
VC_BROKEN_STD::size_t BlockSize() const
{ return blockSize_; }
// Comparison operator for sorting
bool operator<(VC_BROKEN_STD::size_t rhs) const
{ return BlockSize() < rhs; }
};
////////////////////////////////////////////////////////////////////////////////
// class SmallObjAllocator
// Offers services for allocating small-sized objects
////////////////////////////////////////////////////////////////////////////////
class SmallObjAllocator
{
public:
SmallObjAllocator(
VC_BROKEN_STD::size_t chunkSize,
VC_BROKEN_STD::size_t maxObjectSize);
void* Allocate(VC_BROKEN_STD::size_t numBytes);
void Deallocate(void* p, VC_BROKEN_STD::size_t size);
private:
SmallObjAllocator(const SmallObjAllocator&);
SmallObjAllocator& operator=(const SmallObjAllocator&);
typedef std::vector<FixedAllocator> Pool;
Pool pool_;
FixedAllocator* pLastAlloc_;
FixedAllocator* pLastDealloc_;
VC_BROKEN_STD::size_t chunkSize_;
VC_BROKEN_STD::size_t maxObjectSize_;
};
////////////////////////////////////////////////////////////////////////////////
// class SmallObject
// Base class for polymorphic small objects, offers fast
// allocations/deallocations
////////////////////////////////////////////////////////////////////////////////
template
<
class ThreadingModel = DEFAULT_THREADING,
VC_BROKEN_STD::size_t chunkSize = DEFAULT_CHUNK_SIZE,
VC_BROKEN_STD::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
>
class SmallObject : public
Apply1<ThreadingModel, SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
{
typedef typename Apply1<ThreadingModel, SmallObject<ThreadingModel,
chunkSize, maxSmallObjectSize> > MyThreadingModel;
struct MySmallObjAllocator : public SmallObjAllocator
{
MySmallObjAllocator()
: SmallObjAllocator(chunkSize, maxSmallObjectSize)
{}
};
// The typedef below would make things much simpler,
// but MWCW won't like it
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
// DefaultLifetime, ThreadingModel*/> MyAllocator;
public:
static void* operator new(VC_BROKEN_STD::size_t size)
{
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
return SingletonHolder<MySmallObjAllocator, CreateStatic,
PhoenixSingleton>::Instance().Allocate(size);
#else
return ::operator new(size);
#endif
}
static void operator delete(void* p, VC_BROKEN_STD::size_t size)
{
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
SingletonHolder<MySmallObjAllocator, CreateStatic,
PhoenixSingleton>::Instance().Deallocate(p, size);
#else
::operator delete(p, size);
#endif
}
virtual ~SmallObject() {}
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Oct 11, 2002: ported by Benjamin Kaufmann to MSVC 6.0
////////////////////////////////////////////////////////////////////////////////
#endif // SMALLOBJ_INC_

1447
MSVC/1200/SmartPtr.h Normal file

File diff suppressed because it is too large Load diff

219
MSVC/1200/Threads.h Normal file
View file

@ -0,0 +1,219 @@
#ifndef THREADS_H_
#define THREADS_H_
////////////////////////////////////////////////////////////////////////////////
// macro DEFAULT_THREADING
// Selects the default threading model for certain components of Loki
// If you don't define it, it defaults to single-threaded
// All classes in Loki have configurable threading model; DEFAULT_THREADING
// affects only default template arguments
////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 07, 2002
// note: In this VC 6 port all template policies become non-templates with
// either member-template functions or a nested template struct named In
#ifndef DEFAULT_THREADING
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
#endif
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template SingleThreaded
// Implementation of the ThreadingModel policy used by various classes
// Implements a single-threaded model; no synchronization
////////////////////////////////////////////////////////////////////////////////
class SingleThreaded
{
public:
template <class Host>
struct In
{
struct Lock
{
Lock() {}
explicit Lock(const SingleThreaded&) {}
};
typedef Host VolatileType;
typedef int IntType;
static IntType AtomicAdd(volatile IntType& lval, IntType val)
{ return lval += val; }
static IntType AtomicSubtract(volatile IntType& lval, IntType val)
{ return lval -= val; }
static IntType AtomicMultiply(volatile IntType& lval, IntType val)
{ return lval *= val; }
static IntType AtomicDivide(volatile IntType& lval, IntType val)
{ return lval /= val; }
static IntType AtomicIncrement(volatile IntType& lval)
{ return ++lval; }
static IntType AtomicDecrement(volatile IntType& lval)
{ return --lval; }
// The following function uses the undefined variable val.
// Moreover I couldn't find the function in the orginial loki-lib.
// I therefore commented the function out
/*
static IntType AtomicDivide(volatile IntType& lval)
{ return lval /= val; }
*/
static void AtomicAssign(volatile IntType & lval, IntType val)
{ lval = val; }
static void AtomicAssign(IntType & lval, volatile IntType & val)
{ lval = val; }
};
};
#ifdef _WINDOWS_
////////////////////////////////////////////////////////////////////////////////
// class template ObjectLevelLockable
// Implementation of the ThreadingModel policy used by various classes
// Implements a object-level locking scheme
////////////////////////////////////////////////////////////////////////////////
struct ObjectLevelLockable
{
template <class Host>
struct In
{
private:
CRITICAL_SECTION mtx_;
public:
ObjectLevelLockable()
{
::InitializeCriticalSection(&mtx_);
}
~ObjectLevelLockable()
{
::DeleteCriticalSection(&mtx_);
}
class Lock;
friend class Lock;
class Lock
{
ObjectLevelLockable& host_;
Lock(const Lock&);
Lock& operator=(const Lock&);
Lock(); // buggy design
public:
explicit Lock(ObjectLevelLockable& host) : host_(host)
{
::EnterCriticalSection(&host_.mtx_);
}
~Lock()
{
::LeaveCriticalSection(&host_.mtx_);
}
};
typedef volatile Host VolatileType;
typedef LONG IntType;
static IntType AtomicIncrement(volatile IntType& lval)
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
static IntType AtomicDecrement(volatile IntType& lval)
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
static void AtomicAssign(volatile IntType& lval, IntType val)
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
static void AtomicAssign(IntType& lval, volatile IntType& val)
{ InterlockedExchange(&lval, val); }
};
};
struct ClassLevelLockable
{
template <class Host>
struct In
{
private:
struct Initializer
{
CRITICAL_SECTION mtx_;
Initializer()
{
::InitializeCriticalSection(&mtx_);
}
~Initializer()
{
::DeleteCriticalSection(&mtx_);
}
};
static Initializer initializer_;
public:
class Lock;
friend class Lock;
class Lock
{
Lock(const Lock&);
Lock& operator=(const Lock&);
public:
Lock()
{
::EnterCriticalSection(&initializer_.mtx_);
}
explicit Lock(ClassLevelLockable&)
{
::EnterCriticalSection(&initializer_.mtx_);
}
~Lock()
{
::LeaveCriticalSection(&initializer_.mtx_);
}
};
typedef volatile Host VolatileType;
typedef LONG IntType;
static IntType AtomicIncrement(volatile IntType& lval)
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
static IntType AtomicDecrement(volatile IntType& lval)
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
static void AtomicAssign(volatile IntType& lval, IntType val)
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
static void AtomicAssign(IntType& lval, volatile IntType& val)
{ InterlockedExchange(&lval, val); }
};
};
template <class Host>
typename ClassLevelLockable::template In<Host>::Initializer
ClassLevelLockable::template In<Host>::initializer_;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Oct 06, 2002: ported by Benjamin Kaufmann to MSVC 6.0
////////////////////////////////////////////////////////////////////////////////
#endif

22
MSVC/1200/Tuple.h Normal file
View file

@ -0,0 +1,22 @@
////////////////////////////////////////////////////////////////////////////////
// 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: June 20, 2001
////////////////////////////////////////////////////////////////////////////////
// This file is intentionally left empty
// Due to compiler limitations, its contents has been moved to
// HierarchyGenerators.h
////////////////////////////////////////////////////////////////////////////////

106
MSVC/1200/TypeInfo.h Normal file
View file

@ -0,0 +1,106 @@
////////////////////////////////////////////////////////////////////////////////
// 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: June 20, 2001
#ifndef TYPEINFO_INC_
#define TYPEINFO_INC_
#include <typeinfo>
#include <cassert>
#include "Typelist.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class TypeInfo
// Purpose: offer a first-class, comparable wrapper over std::type_info
////////////////////////////////////////////////////////////////////////////////
class TypeInfo
{
public:
// Constructors
TypeInfo(); // needed for containers
TypeInfo(const std::type_info&); // non-explicit
// Access for the wrapped std::type_info
const std::type_info& Get() const;
// Compatibility functions
bool before(const TypeInfo& rhs) const;
const char* name() const;
private:
const std::type_info* pInfo_;
};
// Implementation
inline TypeInfo::TypeInfo()
{
class Nil {};
pInfo_ = &typeid(Nil);
assert(pInfo_);
}
inline TypeInfo::TypeInfo(const std::type_info& ti)
: pInfo_(&ti)
{ assert(pInfo_); }
inline bool TypeInfo::before(const TypeInfo& rhs) const
{
assert(pInfo_);
return pInfo_->before(*rhs.pInfo_) != 0;
}
inline const std::type_info& TypeInfo::Get() const
{
assert(pInfo_);
return *pInfo_;
}
inline const char* TypeInfo::name() const
{
assert(pInfo_);
return pInfo_->name();
}
// Comparison operators
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
{ return (lhs.Get() == rhs.Get()) != 0; }
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
{ return lhs.before(rhs); }
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs == rhs); }
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
{ return rhs < lhs; }
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs > rhs); }
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs < rhs); }
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEINFO_INC_

268
MSVC/1200/TypeManip.h Normal file
View file

@ -0,0 +1,268 @@
////////////////////////////////////////////////////////////////////////////////
// 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: Oct 17, 2002
#include "static_check.h"
#ifndef TYPEMANIP_INC_
#define TYPEMANIP_INC_
namespace Loki
{
namespace Private
{
typedef char YES;
struct NO {char dummy[3];};
}
////////////////////////////////////////////////////////////////////////////////
// class template Int2Type
// Converts each integral constant into a unique type
// Invocation: Int2Type<v> where v is a compile-time constant integral
// Defines 'value', an enum that evaluates to v
////////////////////////////////////////////////////////////////////////////////
template <int v>
struct Int2Type
{
enum { value = v };
};
////////////////////////////////////////////////////////////////////////////////
// class template Type2Type
// Converts each type into a unique, insipid type
// Invocation Type2Type<T> where T is a type
// Defines the type OriginalType which maps back to T
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct Type2Type
{
typedef T OriginalType;
Type2Type() {};
};
////////////////////////////////////////////////////////////////////////////////
// class template Select
// Selects one of two types based upon a boolean constant
// Invocation: Select<flag, T, U>::Result
// where:
// flag is a compile-time boolean constant
// T and U are types
// Result evaluates to T if flag is true, and to U otherwise.
////////////////////////////////////////////////////////////////////////////////
// VC6 compatible version
namespace Private
{
template <bool>
struct SelectImpl
{
template <class T, class U>
struct In
{
typedef T Result;
};
};
template <>
struct SelectImpl<false>
{
template <class T, class U>
struct In
{
typedef U Result;
};
};
} // end of namespace private
template <bool flag, typename T, typename U>
struct Select
{
typedef typename Private::SelectImpl<flag>::template In<T, U>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template IsEqualType
// Returns true if the two given types are equal
// Invocation: IsEqualType<T, U>::value
// where:
// T and U are types
// Result evaluates to true if U == T (types equal)
////////////////////////////////////////////////////////////////////////////////
// This template is not in the original Loki-Library
template <class T, class U>
struct IsEqualType
{
private:
static Private::YES check(Type2Type<T>);
static Private::NO check(...);
public:
enum {value = sizeof(check(Type2Type<U>())) == sizeof(Private::YES)};
};
////////////////////////////////////////////////////////////////////////////////
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
typedef char Small;
class Big { char dummy[2]; };
// IsVoid from Rani Sharoni's VC 7 port
template<typename T>
struct IsVoid
{
enum { value =
IsEqualType<T, void>::value ||
IsEqualType<T, const void>::value ||
IsEqualType<T, volatile void>::value ||
IsEqualType<T, const volatile void>::value
};
};
}
//
// is one type convertable to another?
//
// is_convertible from Rani Sharoni's VC 7 port.
template <class T, class U>
class is_convertible
{
struct VoidReplace {};
typedef typename Select
<
Private::IsVoid<T>::value,
VoidReplace, T
>
::Result T1;
typedef typename Select
<
Private::IsVoid<U>::value,
VoidReplace, U
>
::Result U1;
static Private::Big Test(...);
static Private::Small Test(U1);
static T1 MakeT();
public:
enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
};
////////////////////////////////////////////////////////////////////////////////
// class template Conversion
// Figures out the conversion relationships between two types
// Invocations (T and U are types):
// a) Conversion<T, U>::exists
// returns (at compile time) true if there is an implicit conversion from T
// to U (example: Derived to Base)
// b) Conversion<T, U>::exists2Way
// returns (at compile time) true if there are both conversions from T
// to U and from U to T (example: int to char and back)
// c) Conversion<T, U>::sameType
// returns (at compile time) true if T and U represent the same type
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
// Conversion-Template from Rani Sharoni's VC 7 port.
template <class T, class U>
struct Conversion
{
enum { exists = (is_convertible<T,U>::exists) };
enum { exists2Way = (exists && is_convertible<U, T>::exists) };
enum { sameType = (IsEqualType<T, U>::value) };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclass
// Invocation: SuperSubclass<B, D>::value where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct SuperSubclass
{
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclassStrict
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template<class T,class U>
struct SuperSubclassStrict
{
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
!::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
};
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS(T, U) \
(::Loki::Conversion<const volatile U*, const volatile T*>::exists && \
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType)
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS_STRICT(T, U) \
(SUPERSUBCLASS(T, U) && \
!::Loki::Conversion<const volatile T *, const volatile U *>::sameType)
template <unsigned i>
struct TypeTag
{
struct Inner {char c[i];};
typedef Inner X;
STATIC_SIZE_ASSERT(X, i);
};
} // 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)
// Sept 29, 2002: ported by Benjamin Kaufmann to MSVC 6
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEMANIP_INC_

302
MSVC/1200/TypeTraits.h Normal file
View file

@ -0,0 +1,302 @@
////////////////////////////////////////////////////////////////////////////////
// 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: Oct 05, 2002
// Most of the code is taken from Rani Sharoni's Loki VC 7 port
// Reference, pointer and array detection is based on boost's type traits
// AdjReference has moved to namespace-scope. Explicit specialization is
// only allowed there.
#ifndef TYPETRAITS_INC_
#define TYPETRAITS_INC_
#include "Typelist.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomUnsignedInt
// Offers a means to integrate nonstandard built-in unsigned integral types
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
// class template defined below.
// Invocation: IsCustomUnsignedInt<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
// integral type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomUnsignedInt
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomSignedInt
// Offers a means to integrate nonstandard built-in unsigned integral types
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
// class template defined below.
// Invocation: IsCustomSignedInt<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in signed
// integral type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomSignedInt
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomFloat
// Offers a means to integrate nonstandard floating point types with the
// TypeTraits class template defined below.
// Invocation: IsCustomFloat<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in
// floating point type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomFloat
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// Helper types for class template TypeTraits defined below
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
typedef TYPELIST_4(unsigned char, unsigned short int,
unsigned int, unsigned long int) StdUnsignedInts;
typedef TYPELIST_4(signed char, short int,
int, long int) StdSignedInts;
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
typedef TYPELIST_3(float, double, long double) StdFloats;
}
////////////////////////////////////////////////////////////////////////////////
// class template TypeTraits
// Figures out various properties of any given type
// Invocations (T is a type):
// a) TypeTraits<T>::isPointer
// returns (at compile time) true if T is a pointer type
// b) TypeTraits<T>::PointeeType
// returns the type to which T points is T is a pointer type, NullType otherwise
// a) TypeTraits<T>::isReference
// returns (at compile time) true if T is a reference type
// b) TypeTraits<T>::ReferredType
// returns the type to which T refers is T is a reference type, NullType
// otherwise
// c) TypeTraits<T>::isMemberPointer
// returns (at compile time) true if T is a pointer to member type
// d) TypeTraits<T>::isStdUnsignedInt
// returns (at compile time) true if T is a standard unsigned integral type
// e) TypeTraits<T>::isStdSignedInt
// returns (at compile time) true if T is a standard signed integral type
// f) TypeTraits<T>::isStdIntegral
// returns (at compile time) true if T is a standard integral type
// g) TypeTraits<T>::isStdFloat
// returns (at compile time) true if T is a standard floating-point type
// h) TypeTraits<T>::isStdArith
// returns (at compile time) true if T is a standard arithmetic type
// i) TypeTraits<T>::isStdFundamental
// returns (at compile time) true if T is a standard fundamental type
// j) TypeTraits<T>::isUnsignedInt
// returns (at compile time) true if T is a unsigned integral type
// k) TypeTraits<T>::isSignedInt
// returns (at compile time) true if T is a signed integral type
// l) TypeTraits<T>::isIntegral
// returns (at compile time) true if T is a integral type
// m) TypeTraits<T>::isFloat
// returns (at compile time) true if T is a floating-point type
// n) TypeTraits<T>::isArith
// returns (at compile time) true if T is a arithmetic type
// o) TypeTraits<T>::isFundamental
// returns (at compile time) true if T is a fundamental type
// p) TypeTraits<T>::ParameterType
// returns the optimal type to be used as a parameter for functions that take Ts
// q) TypeTraits<T>::isConst
// returns (at compile time) true if T is a const-qualified type
// r) TypeTraits<T>::NonConstType
// removes the 'const' qualifier from T, if any
// s) TypeTraits<T>::isVolatile
// returns (at compile time) true if T is a volatile-qualified type
// t) TypeTraits<T>::NonVolatileType
// removes the 'volatile' qualifier from T, if any
// u) TypeTraits<T>::UnqualifiedType
// removes both the 'const' and 'volatile' qualifiers from T, if any
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
struct pointer_helper
{
pointer_helper(const volatile void*);
};
struct EnumFalse{ enum {value = 0};};
struct EnumTrue{ enum {value = 1};};
template<bool IsRef>
struct AdjReference
{
template<typename U>
struct In { typedef U const & Result; };
};
template<>
struct AdjReference<true>
{
template<typename U>
struct In { typedef U Result; };
};
}
template <typename T>
class TypeTraits
{
private:
// static T MakeT(...);
template <class U> struct Wrap{};
struct pointer_helper
{
pointer_helper(const volatile void*);
};
static Private::YES is_pointer(pointer_helper);
static Private::NO is_pointer(...);
// With the VC 6. Rani Sharoni's approach to detect references unfortunately
// results in an error C1001: INTERNER COMPILER- FEHLER
//
// is_reference_helper1 is a function taking a Wrap<T> returning
// a pointer to a function taking a Wrap<T> returning a T&.
// This function can only be used if T is not a reference-Type.
// If T is a reference Type the return type would be
// a function taking a Wrap<T> returning a reference to a T-reference.
// That is illegal, therefore is_reference_helper1(...) is used for
// references.
// In order to detect a reference, use the return-type of is_reference_helper1
// with is_reference_helper2.
//
// this reference-detection approach is based on boost's
// Type-Traits. See: boost::composite_traits.h
template <class T>
static T&(* is_reference_helper1(Wrap<T>) )(Wrap<T>);
static Private::NO is_reference_helper1(...);
template <class T>
static Private::NO is_reference_helper2(T&(*)(Wrap<T>));
static Private::YES is_reference_helper2(...);
template <class T, class U>
static Private::YES is_pointer2member(U T::*);
static Private::NO is_pointer2member(...);
// This function can only be used for non-array-types, because
// functions can't return arrays.
// this array-detection approach is based on boost's
// Type-Traits. See: boost::array_traits.h
template <class T>
static T(* is_array_helper1(Wrap<T>) )(Wrap<T>);
static Private::NO is_array_helper1(...);
template <class T>
static Private::NO is_array_helper2(T(*)(Wrap<T>));
static Private::YES is_array_helper2(...);
template<typename U>
static Private::YES is_const(Wrap<const U>);
static Private::NO is_const(...);
template<typename U>
static Private::YES is_volatile(Wrap<volatile U>);
static Private::NO is_volatile(...);
public:
enum {isReference = sizeof(
is_reference_helper2(
is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)};
// enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
// enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
enum {isArray = sizeof(
is_array_helper1(
is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)};
enum {isVoid = Private::IsVoid<T>::value};
enum { isStdUnsignedInt =
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0 };
enum { isStdSignedInt =
TL::IndexOf<Private::StdSignedInts, T>::value >= 0 };
enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0 };
enum { isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0 };
enum { isStdArith = isStdIntegral || isStdFloat };
enum { isStdFundamental = isStdArith || isStdFloat || isVoid };
enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
enum { isArith = isIntegral || isFloat };
enum { isFundamental = isStdFundamental || isArith || isFloat };
enum {
isConst =
sizeof(is_const(Wrap<T>())) == sizeof(Private::YES)
};
enum {
isVolatile =
sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES)
};
enum { isScalar = isStdArith /* || isPointer */ /* || isMemberPointer */ };
private:
typedef typename Private::AdjReference<isReference || isVoid>::
template In<T>::Result AdjType;
public:
typedef typename Select
<
isScalar || isArray, T, AdjType
>
::Result ParameterType;
//
// We get is_class for free
// BUG - fails with functions types (ICE) and unknown size array
// (but works for other incomplete types)
// (the boost one (Paul Mensonides) is better)
//
enum { isClass =
!isScalar &&
!isArray &&
!isReference &&
!isVoid
};
};
}
////////////////////////////////////////////////////////////////////////////////
// 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)
// Oct 05, 2002: ported by Benjamin Kaufmann to MSVC 6
////////////////////////////////////////////////////////////////////////////////
#endif // TYPETRAITS_INC_

1146
MSVC/1200/Typelist.h Normal file

File diff suppressed because it is too large Load diff

556
MSVC/1200/Visitor.h Normal file
View file

@ -0,0 +1,556 @@
////////////////////////////////////////////////////////////////////////////////
// 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 27, 2002
//
// The original visitor implementation depends heavily on the possibility
// to return an expression of type "cv void" from a functions with a return
// type of cv void (6.6.3).
// Unfortunately the MSVC 6.0 does not allow that. Because I could not think
// of any transparent workaround I decided to create a set of complete new
// classes for the void-case.
// Of course this is a very unattractive solution :-(
// If you know of a better solution, please let me know.
//
// The MSVC 6.0 does not allow void to be a default value for a template parameter.
// I therefore changed all defaults to int.
#ifndef VISITOR_INC_
#define VISITOR_INC_
#include "Typelist.h"
#include "HierarchyGenerators.h"
#include "MSVC6Helpers.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitor
// The base class of any Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
////////////////////////////////////////////////////////////////////////////////
// class template Visitor
// The building block of Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
template <class T, typename R = int/* = void */ >
class Visitor;
////////////////////////////////////////////////////////////////////////////////
// class template Visitor (specialization)
// This specialization is not present in the book. It makes it easier to define
// Visitors for multiple types in a shot by using a typelist. Example:
//
// class SomeVisitor :
// public BaseVisitor // required
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
// public Visitor<Paragraph>
// {
// public:
// void Visit(RasterBitmap&); // visit a RasterBitmap
// void Visit(Paragraph &); // visit a Paragraph
// };
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
// helper for Visitor's the left base class
template <unsigned int ListId>
struct VisitorImplLeft
{
template <class TList, class R>
struct In
{
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
// helper for Visitor's the right base class
template <unsigned int ListId>
struct VisitorImplRight
{
template <class TList, class R>
struct In
{
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
// simulates specialization
// class Visitor<Head, R>
template <>
struct VisitorImplLeft<TL::Private::NoneList_ID>
{
template <class T, class R>
struct In
{
struct Result
{
typedef R ReturnType;
virtual ReturnType Visit(T&) = 0;
};
};
};
// simulates the left base class for the specialization
// class Visitor<Typelist<Head, Tail>, R>
template <>
struct VisitorImplLeft<TL::Private::Typelist_ID>
{
template <class TList, class R>
struct In
{
typedef Visitor<typename TList::Head, R> Result;
};
};
template <>
struct VisitorImplRight<TL::Private::NoneList_ID>
{
template <class TList, class R>
struct In
{
struct Result {};
};
};
// simulates the right base class for the specialization
// class Visitor<Typelist<Head, Tail>, R>
template <>
struct VisitorImplRight<TL::Private::Typelist_ID>
{
template <class TList, class R>
struct In
{
typedef Visitor<typename TList::Tail, R> Result;
};
};
template <>
struct VisitorImplRight<TL::Private::AtomList_ID>
{
template <class TList, class R>
struct In
{
struct Result {};
};
};
// MSVC 6.0 will complain if we try to let Visitor inherit
// directly from VisitorImplLeft/VisitorImplRight
template <class T, class R>
struct VisitorImplLeftWrap
{
struct Dummy{};
typedef typename VisitorImplLeft
<
TL::Private::IsTypelist<T>::type_id == TL::Private::AtomList_ID ?
TL::Private::Typelist_ID :
TL::Private::IsTypelist<T>::type_id
>::template In<T, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
template <class T, class R>
struct VisitorImplRightWrap
{
struct Dummy{};
typedef typename VisitorImplRight
<
TL::Private::IsTypelist<T>::type_id
>::template In<T, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
}
template <class T, typename R>
class Visitor : public Private::VisitorImplLeftWrap<T, R>::Result,
public Private::VisitorImplRightWrap<T, R>::Result
{
public:
typedef R ReturnType;
};
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitorImpl
// Implements non-strict visitation (you can implement only part of the Visit
// functions)
////////////////////////////////////////////////////////////////////////////////
template <class TList, typename R = int /* = void */ > class BaseVisitorImpl;
// class for the void-case
template <class TList> class BaseVisitorImplVoid;
namespace Private
{
template <unsigned int ListTag>
struct BaseVisitorImplHelper
{
template <typename T, typename R>
struct In
{
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::Private::Typelist_ID>
{
template <typename TList, typename R>
struct In
{
typedef BaseVisitorImpl<TList, R> Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::Private::NullType_ID>
{
template <typename TList, typename R>
struct In
{
struct Result {};
};
};
template <class T, class R>
struct BaseVisitorImplWrap
{
struct Dummy {};
typedef typename BaseVisitorImplHelper
<
TL::Private::IsTypelist<typename T::Tail>::
type_id == TL::Private::AtomList_ID ?
TL::Private::Typelist_ID :
TL::Private::IsTypelist<typename T::Tail>::type_id
>::template In<typename T::Tail, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
template <unsigned int ListTag>
struct BaseVisitorImplVoidHelper
{
template <typename T>
struct In
{
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
template<>
struct BaseVisitorImplVoidHelper<TL::Private::Typelist_ID>
{
template <typename TList>
struct In
{
typedef BaseVisitorImplVoid<TList> Result;
};
};
template<>
struct BaseVisitorImplVoidHelper<TL::Private::NullType_ID>
{
template <typename TList>
struct In
{
struct Result {};
};
};
template <class T>
struct BaseVisitorImplVoidWrap
{
struct Dummy {};
typedef typename BaseVisitorImplVoidHelper
<
TL::Private::IsTypelist<typename T::Tail>::
type_id == TL::Private::AtomList_ID ?
TL::Private::Typelist_ID :
TL::Private::IsTypelist<typename T::Tail>::type_id
>::template In<typename T::Tail>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
}
template <class TList, typename R>
class BaseVisitorImpl : public Visitor<typename TList::Head, R>,
public Private::BaseVisitorImplWrap<TList, R>::Result
{
ASSERT_TYPELIST(TList);
public:
// using BaseVisitorImpl<Tail, R>::Visit;
virtual R Visit(typename TList::Head&)
{ return R(); }
};
// class for the void-case
template <class TList>
class BaseVisitorImplVoid : public Visitor<typename TList::Head, void>,
public Private::BaseVisitorImplVoidWrap<TList>::Result
{
ASSERT_TYPELIST(TList);
public:
// using BaseVisitorImpl<Tail, R>::Visit;
virtual void Visit(typename TList::Head&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template DefaultCatchAll
////////////////////////////////////////////////////////////////////////////////
template <typename R, typename Visited>
struct DefaultCatchAll
{
static R OnUnknownVisitor(Visited&, BaseVisitor&)
{ return R(); }
};
// template template parameter workaround.
// use Wrapper-Classes like this to instantiate BaseVisitable
struct DefaultCatchAllWrapper
{
template <class R, class Visited>
struct In
{
typedef DefaultCatchAll<R, Visited> type;
};
};
template <typename R, typename Visited>
struct DefaultCatchAllVoid
{
static R OnUnknownVisitor(Visited&, BaseVisitor&)
{}
};
struct DefaultCatchAllVoidWrapper
{
template <class R, class Visited>
struct In
{
typedef DefaultCatchAllVoid<R, Visited> type;
};
};
////////////////////////////////////////////////////////////////////////////////
// class template NonStrictVisitor
// Implements non-strict visitation (you can implement only part of the Visit
// functions)
////////////////////////////////////////////////////////////////////////////////
template <class T, class Base>
struct NonStrictVisitorUnit : public Base
{
typedef typename Base::ReturnType ReturnType;
ReturnType Visit(T&)
{
return ReturnType();
}
};
struct NonStrictVisitorUnitWrapper
{
template <class T, class B>
struct In
{
typedef NonStrictVisitorUnit<T, B> type;
};
};
template <class TList, typename R = int /* = void */>
class NonStrictVisitor
: public GenLinearHierarchy<
TList,
NonStrictVisitorUnitWrapper,
Visitor<TList, R> >
{
};
template <class T, class Base>
struct NonStrictVisitorUnitVoid : public Base
{
typedef void ReturnType;
ReturnType Visit(T&)
{
}
};
struct NonStrictVisitorUnitVoidWrapper
{
template <class T, class B>
struct In
{
typedef NonStrictVisitorUnitVoid<T, B> type;
};
};
template <class TList>
class NonStrictVisitorVoid
: public GenLinearHierarchy<
TList,
NonStrictVisitorUnitWrapper,
Visitor<TList, void> >
{
};
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitable
////////////////////////////////////////////////////////////////////////////////
template
<
typename R = int/* = void */,
class CatchAll = DefaultCatchAllWrapper
>
class BaseVisitable
{
public:
typedef R ReturnType;
virtual ~BaseVisitable() {}
virtual ReturnType Accept(BaseVisitor&) = 0;
protected: // give access only to the hierarchy
template <class T>
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
{
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
// Apply the Acyclic Visitor
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
{
return p->Visit(visited);
}
return CatchA::OnUnknownVisitor(visited, guest);
}
};
// class for the void-case
template
<
class CatchAll = DefaultCatchAllVoidWrapper
>
class BaseVisitableVoid
{
public:
typedef void ReturnType;
virtual ~BaseVisitableVoid() {}
virtual ReturnType Accept(BaseVisitor&) = 0;
protected: // give access only to the hierarchy
template <class T>
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
{
typedef ApplyInnerType2<CatchAll, void, T>::type CatchA;
// Apply the Acyclic Visitor
if (Visitor<T, void>* p = dynamic_cast<Visitor<T, void>*>(&guest))
{
p->Visit(visited);
}
CatchA::OnUnknownVisitor(visited, guest);
}
};
////////////////////////////////////////////////////////////////////////////////
// macro DEFINE_VISITABLE
// Put it in every class that you want to make visitable (in addition to
// deriving it from BaseVisitable<R>
////////////////////////////////////////////////////////////////////////////////
#define DEFINE_VISITABLE() \
virtual ReturnType Accept(BaseVisitor& guest) \
{ return AcceptImpl(*this, guest); }
#define DEFINE_VISITABLE_VOID() \
virtual void Accept(BaseVisitor& guest) \
{ AcceptImpl(*this, guest); }
////////////////////////////////////////////////////////////////////////////////
// class template CyclicVisitor
// Put it in every class that you want to make visitable (in addition to
// deriving it from BaseVisitable<R>
////////////////////////////////////////////////////////////////////////////////
template <typename R, class TList>
class CyclicVisitor : public Visitor<TList, R>
{
public:
typedef R ReturnType;
// using Visitor<TList, R>::Visit;
template <class Visited>
ReturnType GenericVisit(Visited& host)
{
Visitor<Visited, ReturnType>& subObj = *this;
return subObj.Visit(host);
}
};
template <class TList>
class CyclicVisitorVoid : public Visitor<TList, void>
{
public:
typedef void ReturnType;
// using Visitor<TList, R>::Visit;
template <class Visited>
ReturnType GenericVisit(Visited& host)
{
Visitor<Visited, ReturnType>& subObj = *this;
subObj.Visit(host);
}
};
////////////////////////////////////////////////////////////////////////////////
// macro DEFINE_CYCLIC_VISITABLE
// Put it in every class that you want to make visitable by a cyclic visitor
////////////////////////////////////////////////////////////////////////////////
#define DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
{ return guest.GenericVisit(*this); }
#define DEFINE_CYCLIC_VISITABLE_VOID(SomeVisitor) \
virtual void Accept(SomeVisitor& guest) \
{ guest.GenericVisit(*this); }
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// March 20: add default argument DefaultCatchAll to BaseVisitable
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Oct 27, 2002: ported by Benjamin Kaufmann to MSVC 6.0
////////////////////////////////////////////////////////////////////////////////
#endif // VISITOR_INC_

63
MSVC/1200/static_check.h Normal file
View file

@ -0,0 +1,63 @@
////////////////////////////////////////////////////////////////////////////////
// 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: June 20, 2001
#ifndef STATIC_CHECK_INC_
#define STATIC_CHECK_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// Helper structure for the STATIC_CHECK macro
////////////////////////////////////////////////////////////////////////////////
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
namespace Private
{
template<int x> struct static_assert_test{};
template <bool x> struct SizeError;
template <> struct SizeError<true>{};
}
}
#define STATIC_SIZE_ASSERT(Type, ExpSize) \
typedef ::Loki::Private::static_assert_test<sizeof(::Loki::Private::SizeError \
< (bool) (sizeof(Type) == ExpSize) >)> static_assert_typedef_
////////////////////////////////////////////////////////////////////////////////
// macro STATIC_CHECK
// Invocation: STATIC_CHECK(expr, id)
// where:
// expr is a compile-time integral or pointer expression
// id is a C++ identifier that does not need to be defined
// If expr is zero, id will appear in a compile-time error message.
////////////////////////////////////////////////////////////////////////////////
#define STATIC_CHECK(expr, msg) \
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
////////////////////////////////////////////////////////////////////////////////
// Change log:
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
// definition
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif // STATIC_CHECK_INC_