Rani Sharoni's port

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@33 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
magmaikh 2002-08-15 01:39:30 +00:00
parent b233e001b3
commit 301d96c6a1
26 changed files with 7909 additions and 694 deletions

165
MSVC/1300/AbstractFactory.h Normal file
View file

@ -0,0 +1,165 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef ABSTRACTFACTORY_INC_
#define ABSTRACTFACTORY_INC_
#include "Typelist.h"
#include "TypeManip.h"
#include "HierarchyGenerators.h"
#include <cassert>
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() {}
};
////////////////////////////////////////////////////////////////////////////////
// class template AbstractFactory
// Defines an Abstract Factory interface starting from a typelist
////////////////////////////////////////////////////////////////////////////////
template
<
class TList,
template <class> class Unit = AbstractFactoryUnit
>
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
{
public:
typedef TList ProductList;
template <class T> T* Create()
{
Unit<T>& 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;
ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
{
return new ConcreteProduct;
}
};
////////////////////////////////////////////////////////////////////////////////
// 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_);
return pPrototype_->Clone();
}
private:
AbstractProduct* pPrototype_;
};
////////////////////////////////////////////////////////////////////////////////
// class template ConcreteFactory
// Implements an AbstractFactory interface
////////////////////////////////////////////////////////////////////////////////
template
<
class AbstractFact,
template <class, class> class Creator = OpNewFactoryUnit,
class TList = typename 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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // ABSTRACTFACTORY_INC_

335
MSVC/1300/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() || this->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() && this->operator()(*pos, val) &&
(pos == end() - 1 ||
!this->operator()(val, pos[1]) &&
this->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() && this->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() && this->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/1300/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_

143
MSVC/1300/Factory.h Normal file
View file

@ -0,0 +1,143 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef FACTORY_INC_
#define FACTORY_INC_
#include "LokiTypeInfo.h"
#include "AssocVector.h"
#include <exception>
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template DefaultFactoryError
// Manages the "Unknown Type" error in an object factory
////////////////////////////////////////////////////////////////////////////////
template <typename IdentifierType, class AbstractProduct>
struct DefaultFactoryError
{
struct Exception : public std::exception
{
const char* what() const throw() { return "Unknown Type"; }
};
static AbstractProduct* OnUnknownType(IdentifierType)
{
throw Exception();
}
};
////////////////////////////////////////////////////////////////////////////////
// class template Factory
// Implements a generic object factory
////////////////////////////////////////////////////////////////////////////////
template
<
class AbstractProduct,
typename IdentifierType,
typename ProductCreator = AbstractProduct* (*)(),
template<typename, class>
class FactoryErrorPolicy = DefaultFactoryError
>
class Factory
: public FactoryErrorPolicy<IdentifierType, AbstractProduct>
{
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*),
template<typename, class>
class FactoryErrorPolicy = DefaultFactoryError
>
class CloneFactory
: public FactoryErrorPolicy<TypeInfo, AbstractProduct>
{
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(typeid(*model));
}
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 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // FACTORY_INC_

1347
MSVC/1300/Functor.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,423 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifdef _MSC_VER
#pragma once
#pragma warning( push )
// 'class1' : base-class 'class2' is already a base-class of 'class3'
#pragma warning( disable : 4584 )
#endif // _MSC_VER
#ifndef HIERARCHYGENERATORS_INC_
#define HIERARCHYGENERATORS_INC_
#include "Typelist.h"
#include "TypeTraits.h"
#include "EmptyType.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template GenScatterHierarchy
// Generates a scattered hierarchy starting from a typelist and a template
// Invocation (TList is a typelist, Model is a template of one arg):
// GenScatterHierarchy<TList, Model>
// The generated class inherits all classes generated by instantiating the
// template 'Model' with the types contained in TList
////////////////////////////////////////////////////////////////////////////////
template <typename T, template <typename> class Unit>
class GenScatterHierarchy;
namespace Private
{
// for some reason VC7 needs the base definition altough not in use
template <typename TListTag>
struct GenScatterHierarchyHelper1
{
template <typename T, template <typename> class Unit>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <typename TListTag>
struct GenScatterHierarchyHelper2
{
template <typename T, template <typename> class Unit>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct GenScatterHierarchyHelper1<TL::Typelist_tag>
{
template <class TList, template <typename> class Unit>
struct In
{
typedef GenScatterHierarchy<typename TList::Head, Unit> Result;
};
};
template <>
struct GenScatterHierarchyHelper2<TL::Typelist_tag>
{
template <class TList, template <typename> class Unit>
struct In
{
typedef GenScatterHierarchy<typename TList::Tail, Unit> Result;
};
};
template <>
struct GenScatterHierarchyHelper1<TL::NoneList_tag>
{
template <typename AtomicType, template <typename> class Unit>
struct In { typedef Unit<AtomicType> Result; };
};
template <>
struct GenScatterHierarchyHelper2<TL::NoneList_tag>
{
template <typename AtomicType, template <typename> class Unit>
struct In { struct Result {}; };
};
template <>
struct GenScatterHierarchyHelper1<TL::NullType_tag>
{
template <class TList, template <typename> class Unit>
struct In { struct Result {}; };
};
template <>
struct GenScatterHierarchyHelper2<TL::NullType_tag>
{
template <class TList, template <typename> class Unit>
struct In { struct Result {}; };
};
} // namespace Private
template <typename T, template <typename> class Unit>
class GenScatterHierarchy
: public Private::GenScatterHierarchyHelper1
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, Unit>::Result
, public Private::GenScatterHierarchyHelper2
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, Unit>::Result
{
public:
typedef typename Private::GenScatterHierarchyHelper1
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, Unit>::Result LeftBase;
typedef typename Private::GenScatterHierarchyHelper2
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, Unit>::Result RightBase;
typedef typename Select
<
TL::is_Typelist<T>::value, T, void
>
::Result TList;
template <typename T> struct Rebind
{
typedef Unit<T> Result;
};
};
////////////////////////////////////////////////////////////////////////////////
// function template Field
// Accesses a field in an object of a type generated with GenScatterHierarchy
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
// T is a type in the typelist used to generate H):
// Field<T>(obj)
// returns a reference to Unit<T>, where Unit is the template used to generate H
////////////////////////////////////////////////////////////////////////////////
template <class T, class H>
typename H::template Rebind<T>::Result &
Field(H& obj)
{
return obj;
}
template <class T, class H>
typename H::template Rebind<T>::Result const &
Field(H const & obj)
{
return obj;
}
////////////////////////////////////////////////////////////////////////////////
// function template TupleUnit
// The building block of tuples
////////////////////////////////////////////////////////////////////////////////
template <class T>
struct TupleUnit
{
T value_;
operator T&() { return value_; }
operator const T&() const { return value_; }
};
////////////////////////////////////////////////////////////////////////////////
// class template Tuple
// Implements a tuple class that holds a number of values and provides field
// access to them via the Field function (below)
////////////////////////////////////////////////////////////////////////////////
template <class TList>
struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
{
};
////////////////////////////////////////////////////////////////////////////////
// helper class template FieldHelper
// See Field below
////////////////////////////////////////////////////////////////////////////////
template <unsigned int i>
struct FieldHelper
{
template<class H>
struct In
{
private:
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
typedef typename H::template Rebind<ElementType>::Result UnitType;
enum { isConst = TypeTraits<H>::isConst };
typedef typename Select
<
isConst,
const typename H::RightBase,
typename H::RightBase
>
::Result RightBase;
typedef typename Select
<
SameType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
static ResultType& Do(H& obj)
{
RightBase& rightBase = obj;
return FieldHelper<i - 1>::template In<RightBase>::Do(rightBase);
}
};
};
template <>
struct FieldHelper<0>
{
template<class H>
struct In
{
private:
typedef typename H::TList::Head ElementType;
typedef typename H::template Rebind<ElementType>::Result UnitType;
enum { isConst = TypeTraits<H>::isConst };
typedef typename Select
<
isConst,
const typename H::LeftBase,
typename H::LeftBase
>
::Result LeftBase;
typedef typename Select
<
SameType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
static ResultType& Do(H& obj)
{
LeftBase& leftBase = obj;
return leftBase;
}
};
};
////////////////////////////////////////////////////////////////////////////////
// function template Field
// Accesses a field in an object of a type generated with GenScatterHierarchy
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
// i is the index of a type in the typelist used to generate H):
// Field<i>(obj)
// returns a reference to Unit<T>, where Unit is the template used to generate H
// and T is the i-th type in the typelist
////////////////////////////////////////////////////////////////////////////////
template <unsigned int i, class H>
typename FieldHelper<i>::template In<H>::ResultType&
Field(H& obj)
{
return FieldHelper<i>::template In<H>::Do(obj);
}
////////////////////////////////////////////////////////////////////////////////
// class template GenLinearHierarchy
// Generates a linear hierarchy starting from a typelist and a template
// Invocation (TList is a typelist, Model is a template of two args):
// GenLinearHierarchy<TList, Model, Root>
////////////////////////////////////////////////////////////////////////////////
template
<
class TList,
template <class AtomicType, class UnitBase> class Unit,
class Root = EmptyType
>
class GenLinearHierarchy;
namespace Private
{
template <typename TListTag>
struct GenLinearHierarchyHelper
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::Typelist_tag>
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
typedef Unit< Head, GenLinearHierarchy<Tail, Unit, Root> > Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::NullType_tag>
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
public:
typedef Unit<Head, Root> Result;
};
};
} // namespace Private
template
<
class TList,
template <class AtomicType, class UnitBase> class Unit,
class Root
>
class GenLinearHierarchy
: public Private::GenLinearHierarchyHelper
<
typename TL::is_Typelist<typename TList::Tail>::type_tag
>
::template In<TList, Unit, Root>::Result
{
ASSERT_TYPELIST(TList); // TList must not be NullType
public:
typedef typename Private::GenLinearHierarchyHelper
<
typename TL::is_Typelist<typename TList::Tail>::type_tag
>
::template In<TList, Unit, Root>::Result LinBase;
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // HIERARCHYGENERATORS_INC_
#ifdef _MSC_VER
#pragma warning( pop )
#endif // _MSC_VER

107
MSVC/1300/LokiTypeInfo.h Normal file
View file

@ -0,0 +1,107 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEINFO_INC_

112
MSVC/1300/MinMax.h Normal file
View file

@ -0,0 +1,112 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef MINMAX_INC_
#define MINMAX_INC_
#include "Typelist.h"
#include "TypeTraits.h"
namespace Private
{
typedef TYPELIST_14(
const bool,
const char,
const signed char,
const unsigned char,
const wchar_t,
const short int,
const unsigned short int,
const int,
const unsigned int,
const long int,
const unsigned long int,
const float,
const double,
const long double)
ArithTypes;
}
template <class L, class R>
class MinMaxTraits
{
typedef typename Loki::Select<Loki::Conversion<R, L>::exists,
L, R>::Result
T1;
enum { pos1 = Loki::TL::IndexOf<Private::ArithTypes, const L>::value };
enum { pos2 = Loki::TL::IndexOf<Private::ArithTypes, const R>::value };
typedef Loki::Select<pos1 != -1 && pos1 < pos2, R, T1>::Result T2;
enum { rConst = Loki::TypeTraits<R>::isConst >=
Loki::TypeTraits<L>::isConst };
enum { l2r = rConst && Loki::Conversion<
typename Loki::TypeTraits<L>::NonConstType&,
typename Loki::TypeTraits<R>::NonConstType&>::exists };
typedef typename Loki::Select<l2r, R&, T2>::Result T3;
enum { lConst = Loki::TypeTraits<L>::isConst >=
Loki::TypeTraits<R>::isConst };
enum { r2l = lConst && Loki::Conversion<
typename Loki::TypeTraits<R>::NonConstType&,
typename Loki::TypeTraits<L>::NonConstType&>::exists };
public:
typedef typename Loki::Select<r2l, L&, T3>::Result Result;
};
template <class L, class R>
typename MinMaxTraits<L, R>::Result
Min(L& lhs, R& rhs)
{ if (lhs < rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<const L, R>::Result
Min(const L& lhs, R& rhs)
{ if (lhs < rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<L, const R>::Result
Min(L& lhs, const R& rhs)
{ if (lhs < rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<const L, const R>::Result
Min(const L& lhs, const R& rhs)
{ if (lhs < rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<L, R>::Result
Max(L& lhs, R& rhs)
{ if (lhs > rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<const L, R>::Result
Max(const L& lhs, R& rhs)
{ if (lhs > rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<L, const R>::Result
Max(L& lhs, const R& rhs)
{ if (lhs > rhs) return lhs; return rhs; }
template <class L, class R>
typename MinMaxTraits<const L, const R>::Result
Max(const L& lhs, const R& rhs)
{ if (lhs > rhs) return lhs; return rhs; }
#endif // MINMAX_INC_

418
MSVC/1300/MultiMethods.h Normal file
View file

@ -0,0 +1,418 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef MULTIMETHODS_INC_
#define MULTIMETHODS_INC_
#include "Typelist.h"
#include "LokiTypeInfo.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 = 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 = 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)
{
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
}
template <class SomeLhs, class SomeRhs>
bool Remove()
{
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);
}
////////////////////////////////////////////////////////////////////////////////
// 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);
}
};
////////////////////////////////////////////////////////////////////////////////
// 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);
}
};
////////////////////////////////////////////////////////////////////////////////
// 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 = void,
template <class, class> class CastingPolicy = DynamicCaster,
template <class, class, class, class>
class DispatcherBackend = BasicDispatcher>
class FnDispatcher
{
DispatcherBackend<BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)> backEnd_;
public:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&))
{
return backEnd_.Add<SomeLhs, SomeRhs>(pFun);
}
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add()
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
CastingPolicy<SomeLhs,BaseLhs>,
CastingPolicy<SomeRhs,BaseRhs>,
callback> Local;
Add<SomeLhs, SomeRhs>(&Local::Trampoline);
}
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&),
bool symmetric>
void Add()
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
CastingPolicy<SomeLhs,BaseLhs>,
CastingPolicy<SomeRhs,BaseRhs>,
callback> Local;
Add<SomeLhs, SomeRhs>(&Local::Trampoline);
if (symmetric)
{
Add<SomeRhs, SomeLhs>(&Local::TrampolineR);
}
}
template <class SomeLhs, class SomeRhs>
void Remove()
{
backEnd_.Remove<SomeLhs, SomeRhs>();
}
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 = void,
template <class, class> class CastingPolicy = DynamicCaster,
template <class, class, class, class>
class DispatcherBackend = BasicDispatcher>
class FunctorDispatcher
{
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_;
public:
template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun)
{
typedef Private::FunctorDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
CastingPolicy<SomeLhs, BaseLhs>,
CastingPolicy<SomeRhs, BaseRhs>,
Fun, false> Adapter;
backEnd_.Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun)));
}
template <class SomeLhs, class SomeRhs, bool symmetric, class Fun>
void Add(const Fun& fun)
{
Add<SomeLhs,SomeRhs>(fun);
if (symmetric)
{
// Note: symmetry only makes sense where BaseLhs==BaseRhs
typedef Private::FunctorDispatcherHelper<
BaseLhs, BaseLhs,
SomeLhs, SomeRhs,
ResultType,
CastingPolicy<SomeLhs, BaseLhs>,
CastingPolicy<SomeRhs, BaseLhs>,
Fun, true> AdapterR;
backEnd_.Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun)));
}
}
template <class SomeLhs, class SomeRhs>
void Remove()
{
backEnd_.Remove<SomeLhs, SomeRhs>();
}
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)
////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -13,7 +13,7 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: June 20, 2001 // Last update: May 19, 2002
#ifndef NULLTYPE_INC_ #ifndef NULLTYPE_INC_
#define NULLTYPE_INC_ #define NULLTYPE_INC_
@ -26,12 +26,19 @@ namespace Loki
// Useful as an end marker in typelists // Useful as an end marker in typelists
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class NullType {}; class NullType
{
public:
struct Head { private: Head(); };
struct Tail { private: Tail(); };
};
} }
//////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Change log: // Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // NULLTYPE_INC_ #endif // NULLTYPE_INC_

48
MSVC/1300/Singleton.cpp Normal file
View file

@ -0,0 +1,48 @@
////////////////////////////////////////////////////////////////////////////////
// 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
#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>(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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////

440
MSVC/1300/Singleton.h Normal file
View file

@ -0,0 +1,440 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef SINGLETON_INC_
#define SINGLETON_INC_
#include "Threads.h"
#include <algorithm>
#include <stdexcept>
#include <cassert>
#include <cstdlib>
#include <new>
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 lhs->longevity_ > rhs->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>(
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
std::atexit(Private::AtExitFn);
}
////////////////////////////////////////////////////////////////////////////////
// class template CreateUsingNew
// Implementation of the CreationPolicy used by SingletonHolder
// Creates objects using a straight call to the new operator
////////////////////////////////////////////////////////////////////////////////
template <class T> struct CreateUsingNew
{
static T* Create()
{ return new 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
////////////////////////////////////////////////////////////////////////////////
template <class T> struct CreateUsingMalloc
{
static T* Create()
{
void* p = std::malloc(sizeof(T));
if (!p) return 0;
return new(p) T;
}
static void Destroy(T* p)
{
p->~T();
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.
////////////////////////////////////////////////////////////////////////////////
template <class T> struct CreateStatic
{
#ifdef _MSC_VER
#pragma warning( push )
// alignment of a member was sensitive to packing
#pragma warning( disable : 4121 )
#endif // _MSC_VER
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
static T* Create()
{
static MaxAlign staticMemory_;
return new(&staticMemory_) 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
////////////////////////////////////////////////////////////////////////////////
template <class T>
struct DefaultLifetime
{
static void ScheduleDestruction(T*, void (*pFun)())
{ std::atexit(pFun); }
static void OnDeadReference()
{ 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
////////////////////////////////////////////////////////////////////////////////
template <class T>
class PhoenixSingleton
{
public:
static void ScheduleDestruction(T*, void (*pFun)())
{
#ifndef ATEXIT_FIXED
if (!destroyedOnce_)
#endif
std::atexit(pFun);
}
static void OnDeadReference()
{
#ifndef ATEXIT_FIXED
destroyedOnce_ = true;
#endif
}
private:
#ifndef ATEXIT_FIXED
static bool destroyedOnce_;
#endif
};
#ifndef ATEXIT_FIXED
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
#endif
////////////////////////////////////////////////////////////////////////////////
// class template Adapter
// Helper for SingletonWithLongevity below
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class T>
struct Adapter
{
void operator()(T*) { return pFun_(); }
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
////////////////////////////////////////////////////////////////////////////////
template <class T>
class SingletonWithLongevity
{
public:
static void ScheduleDestruction(T* pObj, void (*pFun)())
{
Private::Adapter<T> adapter = { pFun };
SetLongevity(pObj, GetLongevity(pObj), adapter);
}
static void OnDeadReference()
{ throw std::logic_error("Dead Reference Detected"); }
};
////////////////////////////////////////////////////////////////////////////////
// class template NoDestroy
// Implementation of the LifetimePolicy used by SingletonHolder
// Never destroys the object
////////////////////////////////////////////////////////////////////////////////
template <class T>
struct NoDestroy
{
static void ScheduleDestruction(T*, void (*)())
{}
static void OnDeadReference()
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template SingletonHolder
// Provides Singleton amenities for a type T
// To protect that type from spurious instantiations, you have to protect it
// yourself.
////////////////////////////////////////////////////////////////////////////////
template
<
class ClientType,
class ThreadingModelType,
class PtrInstanceType
>
class SingletonHolderStaticData
{
friend ClientType; // illegal (11.4/2) but works with VC
static ThreadingModelType s_ThreadingModelData;
static PtrInstanceType s_pInstance;
static bool s_destroyed;
};
template<class C, class M, class P>
M SingletonHolderStaticData<C, M, P>::s_ThreadingModelData;
template<class C, class M, class P>
P SingletonHolderStaticData<C, M, P>::s_pInstance;
template<class C, class M, class P>
bool SingletonHolderStaticData<C, M, P>::s_destroyed;
template
<
typename T,
template <class> class CreationPolicy = CreateUsingNew,
template <class> class LifetimePolicy = DefaultLifetime,
template <class> class ThreadingModel = SingleThreaded
>
class SingletonHolder
{
typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
typedef SingletonHolderStaticData
<
SingletonHolder,
ThreadingModel<T>,
PtrInstanceType
>
MySingletonHolderStaticData;
public:
static T& Instance()
{
if (!pInstance_())
{
MakeInstance();
}
return *pInstance_();
}
private:
// Helpers
static void MakeInstance()
{
typename ThreadingModel<T>::Lock guard(
MySingletonHolderStaticData::s_ThreadingModelData);
(void)guard;
if (!pInstance_())
{
if (destroyed_())
{
LifetimePolicy<T>::OnDeadReference();
destroyed_() = false;
}
pInstance_() = CreationPolicy<T>::Create();
LifetimePolicy<T>::ScheduleDestruction
(
pInstance_(),
&DestroySingleton
);
}
}
static void DestroySingleton()
{
assert(!destroyed_());
CreationPolicy<T>::Destroy(pInstance_());
pInstance_() = 0;
destroyed_() = true;
}
// Protection
SingletonHolder();
// Data
static PtrInstanceType &pInstance_()
{
return MySingletonHolderStaticData::s_pInstance;
}
static bool &destroyed_()
{
return MySingletonHolderStaticData::s_destroyed;
}
};
} // 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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // SINGLETON_INC_

418
MSVC/1300/SmallObj.cpp Normal file
View file

@ -0,0 +1,418 @@
////////////////////////////////////////////////////////////////////////////////
// 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: March 20, 2001
#include "SmallObj.h"
#include <cassert>
#include <algorithm>
using namespace Loki;
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Init
// Initializes a chunk object
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Chunk::Init(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(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(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, 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(std::size_t blockSize)
: blockSize_(blockSize)
, allocChunk_(0)
, deallocChunk_(0)
{
assert(blockSize_ > 0);
prev_ = next_ = this;
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 std::size_t chunkLength = numBlocks_ * blockSize_;
Chunk* lo = deallocChunk_;
Chunk* hi = deallocChunk_ + 1;
Chunk* loBound = &chunks_.front();
Chunk* hiBound = &chunks_.back() + 1;
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(
std::size_t chunkSize,
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(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, std::size_t numBytes)
{
if (numBytes > maxObjectSize_) return operator delete(p);
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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////

211
MSVC/1300/SmallObj.h Normal file
View file

@ -0,0 +1,211 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef SMALLOBJ_INC_
#define SMALLOBJ_INC_
#include "Threads.h"
#include "Singleton.h"
#include <cstddef>
#include <vector>
#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(std::size_t blockSize, unsigned char blocks);
void* Allocate(std::size_t blockSize);
void Deallocate(void* p, std::size_t blockSize);
void Reset(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
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(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
std::size_t BlockSize() const
{ return blockSize_; }
// Comparison operator for sorting
bool operator<(std::size_t rhs) const
{ return BlockSize() < rhs; }
};
////////////////////////////////////////////////////////////////////////////////
// class SmallObjAllocator
// Offers services for allocating small-sized objects
////////////////////////////////////////////////////////////////////////////////
class SmallObjAllocator
{
public:
SmallObjAllocator(
std::size_t chunkSize,
std::size_t maxObjectSize);
void* Allocate(std::size_t numBytes);
void Deallocate(void* p, std::size_t size);
private:
SmallObjAllocator(const SmallObjAllocator&);
SmallObjAllocator& operator=(const SmallObjAllocator&);
typedef std::vector<FixedAllocator> Pool;
Pool pool_;
FixedAllocator* pLastAlloc_;
FixedAllocator* pLastDealloc_;
std::size_t chunkSize_;
std::size_t maxObjectSize_;
};
////////////////////////////////////////////////////////////////////////////////
// class SmallObject
// Base class for polymorphic small objects, offers fast
// allocations/deallocations
////////////////////////////////////////////////////////////////////////////////
template
<
class ClientType,
class ThreadingModelType
>
class SmallObjectStaticData
{
friend ClientType; // illegal (11.4/2) but works with VC
static ThreadingModelType s_ThreadingModelData;
};
template<class C, class M>
M SmallObjectStaticData<C, M>::s_ThreadingModelData;
template
<
template <class> class ThreadingModel = DEFAULT_THREADING,
std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
>
class SmallObject : public ThreadingModel<
SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
{
typedef ThreadingModel< SmallObject<ThreadingModel,
chunkSize, maxSmallObjectSize> > MyThreadingModel;
typedef SmallObjectStaticData
<
SmallObject,
MyThreadingModel
>
MySmallObjectStaticData;
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(std::size_t size)
{
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
typename MyThreadingModel::Lock lock(
MySmallObjectStaticData::s_ThreadingModelData);
(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, std::size_t size)
{
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
typename MyThreadingModel::Lock lock(
MySmallObjectStaticData::s_ThreadingModelData);
(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!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // SMALLOBJ_INC_

1329
MSVC/1300/SmartPtr.h Normal file

File diff suppressed because it is too large Load diff

202
MSVC/1300/Threads.h Normal file
View file

@ -0,0 +1,202 @@
#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: June 20, 2001
#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
////////////////////////////////////////////////////////////////////////////////
template <class Host>
class SingleThreaded
{
public:
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; }
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
////////////////////////////////////////////////////////////////////////////////
template <class Host>
class ObjectLevelLockable
{
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); }
};
template <class Host>
class ClassLevelLockable
{
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<Host>::Initializer
ClassLevelLockable<Host>::initializer_;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -13,12 +13,7 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: June 20, 2001 // Last update: May 19, 2002
// MKH
// Copy of TypeInfo.h made to that #include "Typelist.h" gets the local
// flavor instead of the reference implementation
// Added a couple of #pramga warning(disable:4800) becase we just don't care.
#ifndef TYPEINFO_INC_ #ifndef TYPEINFO_INC_
#define TYPEINFO_INC_ #define TYPEINFO_INC_
@ -67,10 +62,7 @@ namespace Loki
inline bool TypeInfo::before(const TypeInfo& rhs) const inline bool TypeInfo::before(const TypeInfo& rhs) const
{ {
assert(pInfo_); assert(pInfo_);
#pragma warning(push) return pInfo_->before(*rhs.pInfo_) != 0;
#pragma warning(disable: 4800)
return pInfo_->before(*rhs.pInfo_);
#pragma warning(pop)
} }
inline const std::type_info& TypeInfo::Get() const inline const std::type_info& TypeInfo::Get() const
@ -88,12 +80,7 @@ namespace Loki
// Comparison operators // Comparison operators
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs) inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
{ { return (lhs.Get() == rhs.Get()) != 0; }
#pragma warning(push)
#pragma warning(disable: 4800)
return lhs.Get() == rhs.Get();
#pragma warning(pop)
}
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs) inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
{ return lhs.before(rhs); } { return lhs.before(rhs); }
@ -114,6 +101,7 @@ namespace Loki
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Change log: // Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // TYPEINFO_INC_ #endif // TYPEINFO_INC_

View file

@ -13,12 +13,13 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: August 22, 2001 // Last update: May 19, 2002
#ifndef TYPELIST_INC_ #ifndef TYPELIST_INC_
#define TYPELIST_INC_ #define TYPELIST_INC_
#include "NullType.h" #include "static_check.h"
#include "Nulltype.h"
#include "TypeManip.h" #include "TypeManip.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -301,7 +302,7 @@
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45) > T41, T42, T43, T44, T45, T46) >
#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ #define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
@ -367,6 +368,122 @@ namespace Loki
namespace TL namespace TL
{ {
////////////////////////////////////////////////////////////////////////////////
// class template MakeTypelist
// Takes a number of arguments equal to its numeric suffix
// The arguments are type names.
// MakeTypeList<T1, T2, ...>::Result
// returns a typelist that is of T1, T2, ...
////////////////////////////////////////////////////////////////////////////////
template
<
typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
>
struct MakeTypeList
{
private:
typedef typename MakeTypeList
<
T2 , T3 , T4 ,
T5 , T6 , T7 ,
T8 , T9 , T10,
T11, T12, T13,
T14, T15, T16,
T17, T18
>
::Result TailResult;
public:
typedef Typelist<T1, TailResult> Result;
};
template<>
struct MakeTypeList
<
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType,
NullType, NullType, NullType
>{
typedef NullType Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template is_Typelist
// detects if type is Typelist (including Nulltype)
// Invocation :
// is_Typelist<T>::value
// returns a compile-time boolean constant containing true iff T is some Typelist<T1,T2>
// is_Typelist<T>::type_id
// returns a compile-time unsigned constant containing
// 1 iff T == Typelist<T1,T2>, 2 iff T == NullType and 3 otherwise
////////////////////////////////////////////////////////////////////////////////
struct Typelist_tag {};
struct NullType_tag {};
struct NoneList_tag {};
enum
{
Typelist_ID = 1,
NullType_ID = 2,
NoneList_ID = 3
};
template<typename T>
struct is_Typelist
{
private:
typedef char (&ye1)[Typelist_ID];
typedef char (&ye2)[NullType_ID];
typedef char (&no) [NoneList_ID];
template<typename Head, typename Tail>
static ye1 check(Type2Type< Typelist<Head, Tail> >);
static ye2 check(Type2Type<NullType>);
static no check(...);
public:
// VC7 fail NPS_HierarchyGenerators.h if this one is enum
static const unsigned int type_id = sizeof(check( Type2Type<T>() ));
enum { value = type_id != sizeof(no) };
typedef typename Select
<
type_id == Typelist_ID,
Typelist_tag,
typename Select<type_id == NullType_ID, NullType_tag, NoneList_tag>::Result
>
::Result type_tag;
};
#ifndef TL_FAST_COMPILATION
// this macro will cause compile time error if _type_ is not a Typelist or NullType
#define ASSERT_TYPELIST(_type_) \
STATIC_CHECK( ::Loki::TL::is_Typelist<_type_>::value, TList_is_not_legal_Typelist )
#else
// might improve the compilation time
#define ASSERT_TYPELIST(_type_) \
typedef char _type_##_is_not_a_Typelist[true]
#endif // ndef TL_FAST_COMPILATION
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Length // class template Length
// Computes the length of a typelist // Computes the length of a typelist
@ -375,24 +492,11 @@ namespace Loki
// returns a compile-time constant containing the length of TList, not counting // returns a compile-time constant containing the length of TList, not counting
// the end terminator (which by convention is NullType) // the end terminator (which by convention is NullType)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//*
namespace Length_
{
template <typename T>
struct HeadLength
{
enum { value = 1 };
};
template <>
struct HeadLength<NullType>
{
enum { value = 0 };
};
}//ns TL::Length_
//*/
template <class TList> struct Length; template <class TList> struct Length;
template <> struct Length<NullType>
template <>
struct Length<NullType>
{ {
enum { value = 0 }; enum { value = 0 };
}; };
@ -400,11 +504,16 @@ namespace Loki
template <class TList> template <class TList>
struct Length struct Length
{ {
enum { value = (Length_::HeadLength<typename TList::Head>::value private:
+ ASSERT_TYPELIST(TList);
Length<typename TList::Tail>::value) };
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
enum { value = 1 + Length<Tail>::value };
}; };
//*/
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template TypeAt // class template TypeAt
// Finds the type at a given index in a typelist // Finds the type at a given index in a typelist
@ -415,31 +524,31 @@ namespace Loki
// If you pass an out-of-bounds index, the result is a compile-time error // If you pass an out-of-bounds index, the result is a compile-time error
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace TypeAt_ { template <class TList, unsigned int index>
struct TypeAt
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
ASSERT_TYPELIST(TList);
template<unsigned int i> template<unsigned int i>
struct Index { struct In
template<class TList> {
struct Which { typedef typename TypeAt<Tail, i - 1>::Result Result;
typedef typename Index<i - 1>::Which<typename TList::Tail>::Result Result; };
};
};
template<> template<>
struct Index<0> { struct In<0>
template<class TList> {
struct Which { typedef Head Result;
typedef typename TList::Head Result; };
};
};
} // namespace TypeAt_
template<class TList, unsigned int i>
struct TypeAt {
typedef typename TypeAt_::Index<i>::Which<TList>::Result Result;
};
public:
typedef typename In<index>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template TypeAtNonStrict // class template TypeAtNonStrict
// Finds the type at a given index in a typelist // Finds the type at a given index in a typelist
@ -452,55 +561,42 @@ namespace Loki
// returns the type in position 'index' in TList, or D if index is out-of-bounds // returns the type in position 'index' in TList, or D if index is out-of-bounds
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace TypeAtNonStrict_ {
template<class TList> template <class TList, unsigned int index, typename DefaultType = NullType>
struct ListType; struct TypeAtNonStrict
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
ASSERT_TYPELIST(TList);
template<unsigned int index> template<class TList1,unsigned int i>
struct Index; struct In
{
typedef typename TypeAtNonStrict
<
typename TList1::Tail,
i - 1,
DefaultType
>
::Result Result;
};
template<> template<>
struct ListType<NullType> { struct In<Typelist<Head, Tail>, 0>
template<unsigned int index, typename DefaultType> {
struct Remainder { typedef Head Result;
typedef DefaultType Result; };
};
};
template<> template<>
struct Index<0> { struct In<NullType, index>
template<class TList, typename DefaultType> {
struct Remainder { typedef DefaultType Result;
typedef typename TList::Head Result; };
}; public:
}; typedef typename In<TList, index>::Result Result;
};
template<unsigned int index>
struct Index {
template<class TList, typename DefaultType>
struct Remainder {
enum { isSameType = Conversion<NullType, typename TList::Tail>::sameType };
typedef typename Select<isSameType, NullType, typename Index<index - 1>::Remainder<typename TList::Tail, DefaultType>::Result>::Result Result;
};
};
template<class TList>
struct ListType {
template<unsigned int index, typename DefaultType>
struct Remainder {
typedef typename Index<index>::Remainder<TList, DefaultType>::Result Result;
};
};
} // namespace TypeAtNonStrict_
template<class TList, unsigned int index, typename DefaultType = NullType>
struct TypeAtNonStrict {
typedef typename TypeAtNonStrict_::ListType<TList>::Remainder<index, DefaultType>::Result Result;
};
} // namespace TL
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template IndexOf // class template IndexOf
@ -510,67 +606,43 @@ namespace Loki
// returns the position of T in TList, or NullType if T is not found in TList // returns the position of T in TList, or NullType if T is not found in TList
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private { template <class TList, class T>
struct IndexOf
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
ASSERT_TYPELIST(TList);
namespace IndexOf_ { template<class TList1>
struct In
{
private:
typedef typename TList1::Tail Tail;
template<typename TList> enum { temp = (IndexOf<Tail, T>::value) };
struct Head {
typedef typename TList::Head Result;
};
template<> public:
struct Head<NullType> { enum { value = temp == -1 ? -1 : 1 + temp };
typedef void Result; };
};
struct IsNull { template<>
enum { value = -1 }; struct In< Typelist<T, Tail> >
}; {
enum { value = 0 };
};
struct IsTHead { template<>
enum { value = 0 }; struct In<NullType>
}; {
enum { value = -1 };
};
template<typename TList, typename T> public:
struct IsNotTHead { enum { value = In<TList>::value };
typedef typename TList::Tail Tail; };
typedef typename Select<is_same<Tail, NullType>::result,
IsNull,
typename Select<is_same<typename Head<Tail>::Result, T>::result,
IsTHead, IsNotTHead<Tail, T>
>::Result
>::Result chooser;
enum { temp = chooser::value };
enum { value = temp == -1 ? -1 : 1 + temp };
};
template<typename TList, typename T>
struct IsNotNull {
typedef typename Select<is_same<typename TList::Head, T>::result,
IsTHead,
IsNotTHead<TList, T>
>::Result chooser;
enum { value = chooser::value };
};
} // namespace IndexOf_
} // namespace Private
namespace TL {
template<class TList, class T>
struct IndexOf {
private:
typedef typename Select<Private::is_same<TList, NullType>::result,
Private::IndexOf_::IsNull,
Private::IndexOf_::IsNotNull<TList, T>
>::Result chooser;
public:
enum { value = chooser::value };
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Append // class template Append
// Appends a type or a typelist to another // Appends a type or a typelist to another
@ -579,37 +651,42 @@ public:
// returns a typelist that is TList followed by T and NullType-terminated // returns a typelist that is TList followed by T and NullType-terminated
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Append_ { template <class TList, class T>
struct Append
template<class T> {
struct Helper { typedef typename TList::Head Head;
struct big { char i[2]; }; typedef typename TList::Tail Tail;
template<class Head, class Tail>
static char Test(const Typelist<Head, Tail>&);
static big Test(...);
static T makeT();
};
} // namespace Append_
template<class TList, class T>
struct Append;
template<> private:
struct Append<NullType, NullType> { ASSERT_TYPELIST(TList);
typedef NullType Result;
};
template<class TList, class T> template<class TList1>
struct Append { struct In
private: {
enum { T_is_list = sizeof(Append_::Helper<T>::Test(Append_::Helper<T>::MakeT())) == sizeof(char) }; typedef typename TList1::Tail Tail;
enum { TList_is_null = Conversion<TList, NullType>::sameType };
typedef typename Select<TList_is_null & T_is_list, T, NullType>::Result Result1; typedef Typelist
typedef typename Select<TList_is_null & !T_is_list, Typelist<T, NullType>, Result1>::Result Result2; <
public: Head,
typedef typename Select<!TList_is_null & !T_is_list, Typelist<typename TList::Head, typename Append<typename TList::Tail, T>::Result>, Result2>::Result Result; typename Append<Tail, T>::Result
}; >
Result;
};
template<>
struct In<NullType>
{
typedef typename Select
<
is_Typelist<T>::value,
T, TYPELIST_1(T)
>
::Result Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Erase // class template Erase
@ -619,15 +696,43 @@ public:
// returns a typelist that is TList without the first occurence of T // returns a typelist that is TList without the first occurence of T
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList, class T> template <class TList, class T>
struct Erase { struct Erase
private: {
enum { TList_is_null = Conversion<TList, NullType>::sameType }; typedef typename TList::Head Head;
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType }; typedef typename TList::Tail Tail;
typedef typename Select<!TList_is_null & Head_is_T, typename TList::Tail, NullType>::Result Result1;
public: private:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Erase<typename TList::Tail, T>::Result>, Result1>::Result Result; ASSERT_TYPELIST(TList);
};
template<class TList1>
struct In
{
typedef typename TList1::Tail Tail;
typedef Typelist
<
Head,
typename Erase<Tail, T>::Result
>
Result;
};
template<>
struct In< Typelist<T, Tail> >
{
typedef Tail Result;
};
template<>
struct In<NullType>
{
typedef NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template EraseAll // class template EraseAll
@ -637,15 +742,41 @@ public:
// returns a typelist that is TList without any occurence of T // returns a typelist that is TList without any occurence of T
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList, class T> template <class TList, class T>
struct EraseAll { struct EraseAll
private: {
enum { TList_is_null = Conversion<TList, NullType>::sameType }; typedef typename TList::Head Head;
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType }; typedef typename TList::Tail Tail;
typedef typename Select<!TList_is_null & Head_is_T, typename EraseAll<typename TList::Tail, T>::Result, NullType>::Result Result1;
public: private:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename EraseAll<typename TList::Tail, T>::Result>, Result1>::Result Result; ASSERT_TYPELIST(TList);
};
template<class TList1>
struct In
{
private:
typedef typename TList1::Tail Tail;
typedef typename EraseAll<Tail, T>::Result TailResult;
public:
typedef typename Select
<
SameType<Head, T>::value,
TailResult,
Typelist<Head, TailResult>
>
::Result Result;
};
template<>
struct In<NullType>
{
typedef NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template NoDuplicates // class template NoDuplicates
@ -654,23 +785,27 @@ public:
// NoDuplicates<TList, T>::Result // NoDuplicates<TList, T>::Result
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList> template <class TList>
struct NoDuplicates; struct NoDuplicates
{
private:
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
ASSERT_TYPELIST(TList);
template<> typedef typename NoDuplicates<Tail>::Result L1;
struct NoDuplicates<NullType> { typedef typename Erase<L1, Head>::Result L2;
typedef NullType Result;
};
template<class TList>
struct NoDuplicates {
private:
typedef typename NoDuplicates<typename TList::Tail>::Result L1;
typedef typename Erase<L1, typename TList::Head>::Result L2;
public:
typedef Typelist<typename TList::Head, L2> Result;
};
public:
typedef Typelist<Head, L2> Result;
};
template <>
struct NoDuplicates<NullType>
{
typedef NullType Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Replace // class template Replace
@ -680,16 +815,44 @@ public:
// returns a typelist in which the first occurence of T is replaced with U // returns a typelist in which the first occurence of T is replaced with U
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList, class T, class U> template <class TList, class T, class U>
struct Replace { struct Replace
private: {
enum { TList_is_null = Conversion<TList, NullType>::sameType }; typedef typename TList::Head Head;
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType }; typedef typename TList::Tail Tail;
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename TList::Tail>, NullType>::Result Result1;
public:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Replace<typename TList::Tail, T, U>::Result>, Result1>::Result Result;
};
private:
ASSERT_TYPELIST(TList);
template<class TList1>
struct In
{
typedef typename TList1::Tail Tail;
typedef Typelist
<
Head,
typename Replace<Tail, T, U>::Result
>
Result;
};
template<>
struct In< Typelist<T, Tail> >
{
typedef Typelist<U, Tail> Result;
};
template<>
struct In<NullType>
{
typedef NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template ReplaceAll // class template ReplaceAll
// Replaces all occurences of a type in a typelist, with another type // Replaces all occurences of a type in a typelist, with another type
@ -698,16 +861,42 @@ public:
// returns a typelist in which all occurences of T is replaced with U // returns a typelist in which all occurences of T is replaced with U
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList, class T, class U> template <class TList, class T, class U>
struct ReplaceAll { struct ReplaceAll
private: {
enum { TList_is_null = Conversion<TList, NullType>::sameType }; typedef typename TList::Head Head;
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType }; typedef typename TList::Tail Tail;
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename ReplaceAll<typename TList::Tail, T, U>::Result>, NullType>::Result Result1;
public: private:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename ReplaceAll<typename TList::Tail, T, U>::Result>, Result1>::Result Result; ASSERT_TYPELIST(TList);
};
template<class TList1>
struct In
{
private:
typedef typename TList1::Tail Tail;
typedef typename ReplaceAll<Tail, T, U>::Result TailResult;
public:
typedef typename Select
<
SameType<Head, T>::value,
Typelist<U, TailResult>,
Typelist<Head, TailResult>
>
::Result Result;
};
template<>
struct In<NullType>
{
typedef NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Reverse // class template Reverse
// Reverses a typelist // Reverses a typelist
@ -716,18 +905,28 @@ public:
// returns a typelist that is TList reversed // returns a typelist that is TList reversed
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList> template <class TList> struct Reverse;
struct Reverse {
private: template <>
enum { list_of_one = Conversion<typename TList::Tail, NullType>::sameType }; struct Reverse<NullType>
public: {
typedef typename Select<list_of_one, typedef NullType Result;
TList, };
typename Append<typename Reverse<typename TList::Tail>::Result,
typename TList::Head template <class TList>
>::Result struct Reverse
>::Result Result; {
}; private:
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
ASSERT_TYPELIST(TList);
public:
typedef typename Append<
typename Reverse<Tail>::Result, Head>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template MostDerived // class template MostDerived
@ -737,18 +936,41 @@ public:
// returns the type in TList that's the most derived from T // returns the type in TList that's the most derived from T
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<class TList, class T> template <class TList, class T>
struct MostDerived { struct MostDerived
private: {
enum { TList_is_null = Conversion<TList, NullType>::sameType }; typedef typename TList::Head Head;
typedef typename Select<TList_is_null, T, typename MostDerived<typename TList::Tail, T>::Result>::Result Candidate; typedef typename TList::Tail Tail;
public:
typedef typename Select<TList_is_null, T, private:
typename Select<SUPERSUBCLASS(Candidate, typename TList::Head), ASSERT_TYPELIST(TList);
typename TList::Head, Candidate
>::Result template<class TList1>
>::Result Result; struct In
}; {
private:
typedef typename TList1::Tail Tail;
typedef typename TList1::Head Head;
typedef typename MostDerived<Tail, T>::Result Candidate;
public:
typedef typename Select
<
SUPERSUBCLASS(Candidate, Head),
Head, Candidate
>
::Result Result;
};
template<>
struct In<NullType>
{
typedef T Result;
};
public:
typedef typename In<TList>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template DerivedToFront // class template DerivedToFront
@ -757,41 +979,68 @@ public:
// DerivedToFront<TList>::Result // DerivedToFront<TList>::Result
// returns the reordered TList // returns the reordered TList
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace DerivedToFront_ {
template<class TList>
struct ListType {
};
template<>
struct ListType<NullType> {
typedef NullType Result;
};
} // namespace DerivedToFront_
template<class TList>
struct DerivedToFront;
template<> template <class TList> struct DerivedToFront;
struct DerivedToFront<NullType> {
typedef NullType Result;
};
template<class TList> template <>
struct DerivedToFront { struct DerivedToFront<NullType>
private: {
typedef typename MostDerived<typename TList::Tail, typedef NullType Result;
typename TList::Head>::Result TheMostDerived; };
typedef typename Replace<typename TList::Tail, TheMostDerived,
typename TList::Head>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result;
};
} // namespace TL template <class TList>
struct DerivedToFront
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
typedef typename ReplaceAll<Tail, TheMostDerived, Head>::Result Temp;
typedef typename DerivedToFront<Temp>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template DerivedToFrontAll
// Arranges all the types in a typelist so that the most derived types appear first
// Invocation (TList is a typelist):
// DerivedToFront<TList>::Result
// returns the reordered TList
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct DerivedToFrontAll;
template <>
struct DerivedToFrontAll<NullType>
{
typedef NullType Result;
};
template <class TList>
struct DerivedToFrontAll
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
typedef typename DerivedToFrontAll<L>::Result TailResult;
public:
typedef Typelist<TheMostDerived, TailResult> Result;
};
} // namespace TL
} // namespace Loki } // namespace Loki
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -799,7 +1048,7 @@ public:
// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27 // June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27
// (credit due to Dave Taylor) // (credit due to Dave Taylor)
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC // May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // TYPELIST_INC_ #endif // TYPELIST_INC_

View file

@ -13,24 +13,13 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: August 22, 2001 // Last update: May 19, 2002
#ifndef TYPEMANIP_INC_ #ifndef TYPEMANIP_INC_
#define TYPEMANIP_INC_ #define TYPEMANIP_INC_
namespace Loki { namespace Loki
{
namespace Private {
struct big { char c[2]; };
struct any {
template<typename T>
any(const T&);
};
} // namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Int2Type // class template Int2Type
// Converts each integral constant into a unique type // Converts each integral constant into a unique type
@ -53,8 +42,9 @@ namespace Loki {
template <typename T> template <typename T>
struct Type2Type struct Type2Type
{ {
typedef T OriginalType; typedef T OriginalType;
Type2Type(){} // VC7
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -67,96 +57,98 @@ namespace Loki {
// Result evaluates to T if flag is true, and to U otherwise. // Result evaluates to T if flag is true, and to U otherwise.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private { template <bool flag, typename T, typename U>
struct Select
{
private:
template<bool>
struct In
{ typedef T Result; };
namespace Select_ { template<>
struct In<false>
{ typedef U Result; };
struct ChooseT { public:
template<typename T, typename U> typedef typename In<flag>::Result Result;
struct Choose { };
typedef T Result;
};
};
struct ChooseU { ////////////////////////////////////////////////////////////////////////////////
template<typename T, typename U> // class template SameType
struct Choose { // Return true iff two given types are the same
typedef U Result; // Invocation: SameType<T, U>::value
}; // where:
}; // T and U are types
// Result evaluates to true iff U == T (types equal)
////////////////////////////////////////////////////////////////////////////////
template<bool flag> template <typename T, typename U>
struct Selector { struct SameType
typedef ChooseT Result; {
}; private:
template<typename>
struct In
{ enum { value = false }; };
template<> template<>
struct Selector<false> { struct In<T>
typedef ChooseU Result; { enum { value = true }; };
};
} // namespace Select_ public:
enum { value = In<U>::value };
};
////////////////////////////////////////////////////////////////////////////////
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
////////////////////////////////////////////////////////////////////////////////
} // namespace Private namespace Private
{
typedef char Small;
class Big { char dummy[2]; };
template<bool flag, typename T, typename U> template<typename T>
struct Select { struct IsVoid
private: {
typedef typename Private::Select_::Selector<flag>::Result selector; enum { result =
public: SameType<T, void>::value ||
typedef typename selector::Choose<T, U>::Result Result; SameType<T, const void>::value ||
}; SameType<T, volatile void>::value ||
SameType<T, const volatile void>::value
};
};
}
namespace Private { //
// is one type convertable to another?
//
template <class T, class U>
class is_convertible
{
struct VoidReplace {};
template<typename T> typedef typename Select
struct is_void { <
enum { value = 0 }; Private::IsVoid<T>::result,
}; VoidReplace, T
>
::Result T1;
template<> typedef typename Select
struct is_void<void> { <
enum { value = 1 }; Private::IsVoid<U>::result,
}; VoidReplace, U
>
::Result U1;
namespace is_same_ { static Private::Big Test(...);
static Private::Small Test(U1);
static T1 MakeT();
template<typename T> public:
char test_same(T*, T*); enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
};
template<typename T>
big test_same(T*, any);
template<typename T, typename U>
struct is_same_imp {
static T t;
static U u;
enum { result = sizeof(test_same(&t, &u)) == sizeof(char) };
};
} // namespace is_same_
template<typename T, typename U>
struct is_same {
enum { voidT = is_void<T>::value };
enum { voidU = is_void<U>::value };
struct BothVoid {
enum { result = 1 };
};
struct OneVoid {
enum { result = 0 };
};
typedef typename Select<voidT & voidU,
BothVoid,
typename Select<voidT | voidU,
OneVoid,
is_same_::is_same_imp<T, U>
>::Result
>::Result tester;
enum { result = tester::result };
};
} // namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Conversion // class template Conversion
@ -174,65 +166,13 @@ struct is_same {
// Caveat: might not work if T and U are in a private inheritance hierarchy. // Caveat: might not work if T and U are in a private inheritance hierarchy.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private { template <class T, class U>
struct Conversion
namespace Conversion_ { {
enum { exists = (is_convertible<T,U>::exists) };
#ifdef _MSC_VER enum { exists2Way = (exists && is_convertible<U, T>::exists) };
#pragma warning(push) enum { sameType = (SameType<T, U>::value) };
#pragma warning(disable:4181) };
#pragma warning(disable:4800)
#pragma warning(disable:4244)
#endif
template<typename T, typename U>
struct Determine {
template<typename X, typename Y>
struct tester {
static char test(X, Y);
static big test(any, any);
};
static T t;
static U u;
enum { exists = sizeof(tester<T, U>::test(t, t)) == sizeof(char) };
enum { exists2Way = exists & (sizeof(tester<U, T>::test(u, u)) == sizeof(char)) };
enum { sameType = exists2Way & is_same<T, U>::result };
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace Conversion_
} // namespace Private
template<typename T, typename U>
struct Conversion {
private:
enum { voidT = Private::is_void<T>::value };
enum { voidU = Private::is_void<U>::value };
struct both_void {
enum { exists = 1, exists2Way = 1, sameType = 1 };
};
struct one_void {
enum { exists = 1, exists2Way = 0, sameType = 0 };
};
typedef typename Select<voidT & voidU,
both_void,
typename Select<voidT | voidU,
one_void,
Private::Conversion_::Determine<T, U>
>::Result
>::Result Chooser;
public:
enum { exists = Chooser::exists };
enum { exists2Way = Chooser::exists2Way };
enum { sameType = Chooser::sameType };
};
} // namespace Loki
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS // macro SUPERSUBCLASS
@ -244,8 +184,8 @@ public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS(T, U) \ #define SUPERSUBCLASS(T, U) \
(::Loki::Conversion<const U*, const T*>::exists && \ (::Loki::Conversion<const volatile U*, const volatile T*>::exists && \
!::Loki::Conversion<const T*, const void*>::sameType) !::Loki::Conversion<const volatile T*, const volatile void*>::sameType)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS // macro SUPERSUBCLASS
@ -257,12 +197,15 @@ public:
#define SUPERSUBCLASS_STRICT(T, U) \ #define SUPERSUBCLASS_STRICT(T, U) \
(SUPERSUBCLASS(T, U) && \ (SUPERSUBCLASS(T, U) && \
!::Loki::Conversion<const T, const U>::sameType) !::Loki::Conversion<const volatile T *, const volatile U *>::sameType)
} // namespace Loki
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Change log: // Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC6 // May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // TYPEMANIP_INC_ #endif // TYPEMANIP_INC_

View file

@ -1,3 +1,20 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef TYPETRAITS_INC_ #ifndef TYPETRAITS_INC_
#define TYPETRAITS_INC_ #define TYPETRAITS_INC_
@ -21,14 +38,7 @@ namespace Loki
struct IsCustomUnsignedInt struct IsCustomUnsignedInt
{ {
enum { value = 0 }; enum { value = 0 };
}; };
#ifdef _MSC_VER
template<>
struct IsCustomUnsignedInt<unsigned __int64> {
enum { value = 1 };
};
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template IsCustomSignedInt // class template IsCustomSignedInt
@ -48,13 +58,6 @@ namespace Loki
enum { value = 0 }; enum { value = 0 };
}; };
#ifdef _MSC_VER
template<>
struct IsCustomSignedInt<__int64> {
enum { value = 1 };
};
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template IsCustomFloat // class template IsCustomFloat
// Offers a means to integrate nonstandard floating point types with the // Offers a means to integrate nonstandard floating point types with the
@ -84,189 +87,6 @@ namespace Loki
int, long int) StdSignedInts; int, long int) StdSignedInts;
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts; typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
typedef TYPELIST_3(float, double, long double) StdFloats; typedef TYPELIST_3(float, double, long double) StdFloats;
char test_ptr(const volatile void*, const volatile void*);
big test_ptr(any, any);
template<typename T>
T* unrefptr(T&);
char test_const(const volatile void*);
big test_const(volatile void*);
char test_volatile(const volatile void*);
big test_volatile(const void*);
template<typename V, typename X>
char test_mptr(V X::*, any);
big test_mptr(any, any);
template<bool isReference>
struct AddReferenceImp {
template<typename T>
struct Imp {
typedef T Result;
};
};
template<>
struct AddReferenceImp<false> {
template<typename T>
struct Imp {
typedef T& Result;
};
};
#ifndef _MSC_VER
template <class U> struct PointerTraits
{
enum { result = false };
typedef NullType PointeeType;
};
template <class U> struct PointerTraits<U*>
{
enum { result = true };
typedef U PointeeType;
};
#else
template<typename U>
struct PointerTraits {
private:
static U u;
public:
typedef void PointeeType; // unable to determine correctly
enum { result = sizeof(Private::test_ptr(&u, u)) == sizeof(char) };
};
template<>
struct PointerTraits<void> {
typedef void PointeeType;
enum { result = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct ReferenceTraits
{
enum { result = false };
typedef U ReferredType;
};
template <class U> struct ReferenceTraits<U&>
{
enum { result = true };
typedef U ReferredType;
};
#else
#pragma warning(push)
#pragma warning(disable:4181)
template<typename U>
struct ReferenceTraits {
typedef U const volatile cv_u;
static cv_u u;
public:
enum { result = (sizeof(Private::test_const(&u)) != sizeof(char))
| (sizeof(Private::test_volatile(&u)) != sizeof(char)) };
typedef void ReferredType; // unable to determine correctly
};
#pragma warning(pop)
template<>
struct ReferenceTraits<void> {
enum { result = 0 };
typedef void ReferredType;
};
#endif
#ifndef _MSC_VER
template <class U> struct PToMTraits
{
enum { result = false };
};
template <class U, class V>
struct PToMTraits<U V::*>
{
enum { result = true };
};
#else
template<typename U>
struct PToMTraits {
private:
static U u;
public:
enum { result = sizeof(Private::test_mptr(u, &u)) == sizeof(char) };
};
template<>
struct PToMTraits<void> {
enum { result = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct UnConst
{
typedef U Result;
enum { isConst = 0 };
};
template <class U> struct UnConst<const U>
{
typedef U Result;
enum { isConst = 1 };
};
#else
template<typename U>
struct UnConst {
private:
static U u;
public:
typedef void Result; // unable to determine correctly
enum { isConst = sizeof(Private::test_const(Private::unrefptr(u))) == sizeof(char) };
};
template<>
struct UnConst<void> {
typedef void Result;
enum { isConst = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct UnVolatile
{
typedef U Result;
enum { isVolatile = 0 };
};
template <class U> struct UnVolatile<volatile U>
{
typedef U Result;
enum { isVolatile = 1 };
};
#else
template<typename U>
struct UnVolatile {
private:
static U u;
public:
typedef void Result; // unable to determine correctly
enum { isVolatile = sizeof(Private::test_volatile(Private::unrefptr(u))) == sizeof(char) };
};
template<>
struct UnVolatile<void> {
typedef void Result;
enum { isVolatile = 0 };
};
#endif
template<typename U, bool isReference>
struct AddReference {
typedef typename Private::AddReferenceImp<isReference>::template Imp<U>::Result Result;
};
template<>
struct AddReference<void, false> {
typedef void Result;
};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -325,50 +145,203 @@ namespace Loki
template <typename T> template <typename T>
class TypeTraits class TypeTraits
{ {
public: typedef char (&yes)[1];
static const isPointer = Private::PointerTraits<T>::result; typedef char (&no) [2];
//enum { isPointer = Private::PointerTraits<T>::result };
typedef typename Private::PointerTraits<T>::PointeeType PointeeType; template<typename U, size_t N>
static const isReference = Private::ReferenceTraits<T>::result; static void vc7_need_this_for_is_array(Type2Type<U[N]>);
typedef typename Private::ReferenceTraits<T>::ReferredType ReferredType;
template<typename U>
static yes is_reference(Type2Type<U&>);
static no is_reference(...);
template<typename U>
static yes is_pointer1(Type2Type<U*>);
static no is_pointer1(...);
template<typename U>
static yes is_pointer2(Type2Type<U const *>);
static no is_pointer2(...);
template<typename U>
static yes is_pointer3(Type2Type<U volatile *>);
static no is_pointer3(...);
template<typename U>
static yes is_pointer4(Type2Type<U const volatile *>);
static no is_pointer4(...);
template<typename U, typename V>
static yes is_pointer2member(Type2Type<U V::*>);
static no is_pointer2member(...);
template<typename U, size_t N>
static yes is_array1(Type2Type<U[N]>);
static no is_array1(...);
template<typename U>
static yes is_array2(Type2Type<U[]>);
static no is_array2(...);
template<typename U>
static yes is_const(Type2Type<const U>);
static no is_const(...);
template<typename U>
static yes is_volatile(Type2Type<volatile U>);
static no is_volatile(...);
public:
//
// VC7 BUG - will not detect refernce to function
//
enum {
isReference =
sizeof(is_reference(Type2Type<T>())) == sizeof(yes)
};
static const isMemberPointer = Private::PToMTraits<T>::result; //
// VC7 BUG - will not detect pointer to function
//
enum {
isPointer =
sizeof(is_pointer1(Type2Type<T>())) == sizeof(yes) ||
sizeof(is_pointer2(Type2Type<T>())) == sizeof(yes) ||
sizeof(is_pointer3(Type2Type<T>())) == sizeof(yes) ||
sizeof(is_pointer4(Type2Type<T>())) == sizeof(yes)
};
static const isStdUnsignedInt = enum {
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0; isMemberPointer =
static const isStdSignedInt = sizeof(is_pointer2member(Type2Type<T>())) == sizeof(yes)
TL::IndexOf<Private::StdSignedInts, T>::value >= 0; };
static const isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0; enum {
static const isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0; isArray =
static const isStdArith = isStdIntegral || isStdFloat; sizeof(is_array1(Type2Type<T>())) == sizeof(yes) ||
static const isStdFundamental = isStdArith || isStdFloat || sizeof(is_array2(Type2Type<T>())) == sizeof(yes)
Conversion<T, void>::sameType; };
enum {
isVoid =
SameType<T, void>::value ||
SameType<T, const void>::value ||
SameType<T, volatile void>::value ||
SameType<T, const volatile void>::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 };
static const isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value; enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
static const isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value; enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
static const isIntegral = isStdIntegral || isUnsignedInt || isSignedInt; enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
static const isFloat = isStdFloat || IsCustomFloat<T>::value; enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
static const isArith = isIntegral || isFloat; enum { isArith = isIntegral || isFloat };
static const isFundamental = isStdFundamental || isArith || isFloat; enum { isFundamental = isStdFundamental || isArith || isFloat };
typedef typename Select<isStdArith || isPointer || isMemberPointer, T, enum {
typename Private::AddReference<T, isReference>::Result isConst =
>::Result ParameterType; sizeof(is_const(Type2Type<T>())) == sizeof(yes)
};
enum {
isVolatile =
sizeof(is_volatile(Type2Type<T>())) == sizeof(yes)
};
static const isConst = Private::UnConst<T>::isConst; private:
typedef typename Private::UnConst<T>::Result NonConstType; // is_scalar include functions types
static const isVolatile = Private::UnVolatile<T>::isVolatile; struct is_scalar
typedef typename Private::UnVolatile<T>::Result NonVolatileType; {
typedef typename Private::UnVolatile<typename Private::UnConst<T>::Result>::Result private:
UnqualifiedType; struct BoolConvert { BoolConvert(bool); };
static yes check(BoolConvert);
static no check(...);
struct NotScalar {};
typedef typename Select
<
isVoid || isReference || isArray,
NotScalar, T
>
::Result RetType;
static RetType& get();
public:
//
// Ignore forcing value to bool 'true' or 'false' (performance warning)
//
#ifdef _MSC_VER
#pragma warning (disable: 4800)
#endif
enum { value = sizeof(check(get())) == sizeof(yes) };
#ifdef _MSC_VER
#pragma warning (default: 4800)
#endif
}; // is_scalar
private:
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; };
};
typedef typename AdjReference<isReference || isVoid>::
template In<T>::Result AdjType;
public:
enum { isScalar = is_scalar::value };
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: // Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC // May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // TYPETRAITS_INC_ #endif // TYPETRAITS_INC_

106
MSVC/1300/VC_Alignment.h Normal file
View file

@ -0,0 +1,106 @@
// Last update: June 20, 2001
#ifdef _MSC_VER
# pragma once
#else
# error "Visual C++ specific header !"
#endif
#ifndef VC_ALIGNMENT_INC_
#define VC_ALIGNMENT_INC_
#include "Typelist.h"
#include "static_check.h"
////////////////////////////////////////////////////////////////////////////////
// class template MaxAlign
// Computes the maximum alignof for all types in a typelist
// Usage: MaxAlign<TList>::result
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct VC_MaxAlign;
template <>
struct VC_MaxAlign< ::Loki::NullType >
{
enum { result = 0 };
};
template <class TList>
struct VC_MaxAlign
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
enum { headResult = __alignof(Head) };
enum { tailResult = VC_MaxAlign<Tail>::result };
public:
enum { result = headResult > tailResult ?
headResult : tailResult };
};
////////////////////////////////////////////////////////////////////////////////
// class VC_AlignedPODBase
// Defines a host of protected types used by VC_AlignedPOD (defined later)
// Could be just part of VC_AlignedPOD itself, but making it separate ought to
// reduce compile times
////////////////////////////////////////////////////////////////////////////////
class VC_AlignedPODBase
{
protected:
template<unsigned AlignmentSize>
struct AlignedPod
{
STATIC_CHECK(AlignmentSize == 0, BadAlignmentSize_OnlyUpTo128);
};
//
// I used the macro because align(#)
// only works with Integer literals
//
#define ALIGNED_POD(_size_) \
template<> struct AlignedPod<_size_> { \
__declspec(align(_size_)) struct type { char X[_size_]; }; \
enum { alignment = __alignof(type) }; }; \
STATIC_CHECK((_size_ == sizeof(AlignedPod<_size_>::type)), SizeofNotEqualSize); \
STATIC_CHECK((_size_ == (AlignedPod<_size_>::alignment)), SizeofNotEqualAlignof)
ALIGNED_POD(1);
ALIGNED_POD(2);
ALIGNED_POD(4);
ALIGNED_POD(8);
ALIGNED_POD(16);
ALIGNED_POD(32);
ALIGNED_POD(64);
ALIGNED_POD(128);
// can be up to 8192 - is it realistic?
#undef ALIGNED_POD
};
////////////////////////////////////////////////////////////////////////////////
// class template VC_AlignedPOD
// Computes the alignment of all types in a typelist
////////////////////////////////////////////////////////////////////////////////
template <typename TList>
class VC_AlignedPOD : VC_AlignedPODBase
{
enum { maxAlign = VC_MaxAlign<TList>::result };
public:
typedef typename AlignedPod<maxAlign>::type Result;
};
#endif // VC_ALIGNMENT_INC_

864
MSVC/1300/Variant.h Normal file
View file

@ -0,0 +1,864 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001, 2002 by Andrei Alexandrescu
// 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 makes no representations about the suitability of this software
// for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef VARIANT_INC_
#define VARIANT_INC_
#include <cstddef>
#include <memory>
#include <typeinfo>
#include "Visitor.h"
#include "Typelist.h"
#include "static_check.h"
//
// At the moment there is no namespace for Variant
//
#ifdef _MSC_VER
# include "VC_Alignment.h"
#endif
////////////////////////////////////////////////////////////////////////////////
// class template ConfigurableUnion
// Builds a union that contains each type in a typelist
// Usage: ConfigurableUnion<TList> is the very type
////////////////////////////////////////////////////////////////////////////////
template <class U> union ConfigurableUnion;
template <> union ConfigurableUnion< ::Loki::NullType >
{
};
template <class TList>
union ConfigurableUnion
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
Head head_;
ConfigurableUnion<Tail> tail_;
};
////////////////////////////////////////////////////////////////////////////////
// class template MaxSize
// Computes the maximum sizeof for all types in a typelist
// Usage: MaxSize<TList>::result
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct MaxSize;
template <>
struct MaxSize< ::Loki::NullType >
{
enum { result = 0 };
};
template <class TList>
struct MaxSize
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
enum { headResult = sizeof(Head) };
enum { tailResult = MaxSize<Tail>::result };
public:
enum { result = headResult > tailResult ?
headResult : tailResult };
};
////////////////////////////////////////////////////////////////////////////////
// class AlignedPODBase
// Defines a host of protected types used by AlignedPOD (defined later)
// Could be just part of AlignedPOD itself, but making it separate ought to
// reduce compile times
////////////////////////////////////////////////////////////////////////////////
class AlignedPODBase
{
protected:
template <class TList, std::size_t size>
struct ComputeAlignBound
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
template<class TList1>
struct In
{
private:
typedef typename TList1::Head Head1;
typedef typename TList1::Tail Tail1;
typedef typename ComputeAlignBound<Tail1, size>::Result TailResult;
public:
typedef typename ::Loki::Select
<
sizeof(Head1) <= size,
::Loki::Typelist<Head1, TailResult>,
TailResult
>
::Result Result;
};
template<>
struct In< ::Loki::NullType >
{
typedef ::Loki::NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
template <typename U> struct Structify
{ U dummy_; };
class Unknown;
// VC7: fatal error C1067: compiler limit :
// debug information module size exceeded
// Therfore I decreased the list to 26 without
// changing the rage of detectable alignment
typedef TYPELIST_26(
char,
wchar_t,
short int,
int,
long int,
float,
double,
long double,
char*,
void*,
Unknown (*)(Unknown),
Unknown* Unknown::*,
Unknown (Unknown::*)(Unknown),
Structify<char>,
Structify<wchar_t>,
Structify<short int>,
Structify<int>,
Structify<long int>,
Structify<float>,
Structify<double>,
Structify<long double>,
Structify<char*>,
Structify<void*>,
Structify<Unknown (*)(Unknown)>,
Structify<Unknown* Unknown::*>,
Structify<Unknown (Unknown::*)(Unknown)>
)
TypesOfAllAlignments;
};
////////////////////////////////////////////////////////////////////////////////
// class template AlignedPOD
// Computes the alignment of all types in a typelist
// Usage: ConfigurableUnion<TList> is the very type
////////////////////////////////////////////////////////////////////////////////
template <typename TList>
class AlignedPOD : private AlignedPODBase
{
enum { maxSize = MaxSize<TList>::result };
typedef typename ComputeAlignBound
<
TypesOfAllAlignments,
maxSize
>
::Result AlignTypes;
public:
typedef ConfigurableUnion<AlignTypes> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template MakeConst
// Given a typelist TList, returns a typelist that contains the types in TList
// adding a const qualifier to each.
// Usage: MakeConst<TList>::Result
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct MakeConst;
template <> struct MakeConst< ::Loki::NullType >
{
typedef ::Loki::NullType Result; // terminator is not const
};
template <class TList>
struct MakeConst
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
typedef typename MakeConst<Tail>::Result NewTail;
public:
typedef ::Loki::Typelist<const Head, NewTail> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Converter
// Supports the Variant-to-Variant conversion constructor
// Guaranteed to issue an internal compiler error on:
// 1. Metrowerks CodeWarrior 7.0 (internal compiler error: File:
// 'CTemplateTools.c' Line: 1477
// Variant.h line 244 UnitBase > VisitorBase;)
// 2. Microsoft Visual C++ 7.1 alpha release (Assertion failed:
// ( name - nameBuf ) < LIMIT_ID_LENGTH,
// file f:\vs70builds\2108\vc\Compiler\CxxFE\sl\P1\C\outdname.c,
// line 4583)
// 3. GNU gcc 2.95.3-6 (Internal compiler error 980422)
////////////////////////////////////////////////////////////////////////////////
template <class VariantFrom, class VariantTo>
struct Converter
{
//private: VC7 complains
struct UnitBase : public VariantFrom::ConstStrictVisitor
{
protected:
VariantTo* storageForDestination;
};
template <class Type, class Base>
struct Unit : public Base
{
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{
new(this->storageForDestination) VariantTo(obj);
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
typedef typename VariantTo::Types TList;
enum { dispatch = TL::IndexOf<TList, Type>::value > -1 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
private:
typedef ::Loki::GenLinearHierarchy
<
typename VariantFrom::Types,
Unit,
UnitBase
>
VisitorBase;
public:
struct Visitor : public VisitorBase
{
explicit Visitor(VariantTo& dest)
{
// Initialize the pointer to destination
this->storageForDestination = &dest;
}
};
};
////////////////////////////////////////////////////////////////////////////////
// class template ConverterTo
// Supports Variant-to-T conversion
////////////////////////////////////////////////////////////////////////////////
#if 0
template <class VariantFrom, class T>
struct ConverterTo
{
private:
struct DestHolder
: VariantFrom::ConstStrictVisitor
{
protected:
DestHolder() {}
DestHolder(const T& dest) : destination_(dest) {}
T destination_;
};
template <class TList>
struct VisitorBase
: VisitorBase<typename TList::Tail>
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Type;
typedef typename TList::Tail Tail;
protected:
VisitorBase<TList>() {}
VisitorBase<TList>(const T& dest)
: VisitorBase<Tail>(dest) {}
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{ //
// T temp(obj)
// swap(destination_, temp) or destination_ = temp
//
this->destination_ = obj;
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
enum { dispatch = Conversion<Type, T>::exists != 0 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
template <>
struct VisitorBase< ::Loki::NullType >
: DestHolder
{
protected:
VisitorBase< ::Loki::NullType >() {}
VisitorBase< ::Loki::NullType >(const T& dest)
: DestHolder(dest) {}
};
typedef VisitorBase
<
typename VariantFrom::Types
>
VisitorBaseType;
public:
struct Visitor : public VisitorBaseType
{
Visitor() {}
explicit Visitor(const T& dest)
: VisitorBaseType(dest) {}
const T &GetDestination() const
{ return this->destination_; }
};
};
#else
template <class VariantFrom, class T>
struct ConverterTo
{
//private:
struct UnitBase : public VariantFrom::ConstStrictVisitor
{
protected:
T destination_;
};
template <class Type, class Base>
struct Unit : public Base
{
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{
this->destination_ = obj;
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
enum { dispatch = Conversion<Type, T>::exists != 0 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
typedef ::Loki::GenLinearHierarchy<
typename VariantFrom::Types,
Unit,
UnitBase > VisitorBase;
public:
struct Visitor : public VisitorBase
{
const T &GetDestination() const
{ return this->destination_; }
};
};
#endif
namespace Private
{
template<typename T>
struct RawDataKeeper
{
private:
typedef char RawBuffer_t[sizeof(T)];
enum ObjectState_e { eNone, ePreConstruct, ePostConstruct };
T &obj_;
ObjectState_e eObjState_;
RawBuffer_t bufferOrg_;
RawBuffer_t bufferNew_;
private:
void SetObj(const RawBuffer_t &buf) throw()
{
memcpy(&reinterpret_cast<char &>(obj_), buf, sizeof(buf));
}
void GetObj(RawBuffer_t &buf) throw()
{
memcpy(buf, &reinterpret_cast<const char &>(obj_), sizeof(buf));
}
public:
explicit RawDataKeeper(T &obj)
: obj_(obj), eObjState_(eNone)
{}
// add const U & version ?
template<typename U>
void ConstructNew(U &src)
{
assert(eObjState_ == eNone);
GetObj(bufferOrg_);
eObjState_ = ePreConstruct;
new (&obj_) T(src);
eObjState_ = ePostConstruct;
GetObj(bufferNew_);
SetObj(bufferOrg_);
}
void SetNew() throw()
{
assert(eObjState_ == ePostConstruct);
obj_.~T();
SetObj(bufferNew_);
eObjState_ = eNone;
}
~RawDataKeeper()
{
switch(eObjState_)
{
case ePostConstruct:
SetObj(bufferNew_);
obj_.~T();
// fall
case ePreConstruct:
SetObj(bufferOrg_);
// fall
case eNone:
break;
}
}
private:
RawDataKeeper(const RawDataKeeper &);
RawDataKeeper& operator=(const RawDataKeeper &);
};
//
// based on Eric Fridman's safe_swap from boost Variant
//
// strong exception-safety guarantee.
//
// !WARNING!
// SafeSwap CANNOT be safely used in the general case if either
// argument's data members may be accessed concurrently.
//
template<typename T>
void SafeSwap(T &lhs, T &rhs)
{
typedef RawDataKeeper<T> RhsDataKeeper;
typedef RawDataKeeper<T> LhsDataKeeper;
RhsDataKeeper rhsKeeper(rhs);
rhsKeeper.ConstructNew(lhs);
LhsDataKeeper lhsKeeper(lhs);
lhsKeeper.ConstructNew(rhs);
rhsKeeper.SetNew();
lhsKeeper.SetNew();
}
//
// based on Eric Fridman's safe_assign from boost Variant
//
// strong exception-safety guarantee.
//
// !WARNING!
// SafeAssign CANNOT be safely used in the general case if either
// argument's data members may be accessed concurrently.
//
template<typename T, typename U>
void SafeAssign(T &lhs, const U &src)
{
typedef RawDataKeeper<T> LhsDataKeeper;
LhsDataKeeper lhsKeeper(lhs);
lhsKeeper.ConstructNew(src);
lhsKeeper.SetNew();
}
template<typename T>
inline void SwapHelper(T &lhs, T &rhs)
{
using namespace std;
swap(lhs, rhs);
}
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template Variant
// Implements a discriminated union in C++
////////////////////////////////////////////////////////////////////////////////
template <class TList, class AlignedPODType = AlignedPOD<TList> >
class Variant
{
// VC7: fatal error C1067: compiler limit :
// debug information module size exceeded
// Therfore define this type here
typedef typename AlignedPODType::Result Align;
public:
typedef TList Types;
// Default constructor
// Initializes the Variant with a default-constructed object of the
// first type in the typelist
Variant()
{
typedef typename TList::Head T;
new(&buffer_[0]) T;
vptr_ = VTableImpl<T>::GetVPTR();
}
// Copy constructor
Variant(const Variant& rhs)
{
(rhs.vptr_->clone_)(rhs, *this);
}
private:
// Converting constructor; accepts any type in the typelist
// @@@ Suggested simple improvement: accept any type convertible to one of
// the types in the typelist. Use Loki::Conversion as a building block
template <class T>
void VariantConstruct(const T& val, double)
{
STATIC_CHECK((::Loki::TL::IndexOf<TList, T>::value >= 0),
Invalid_Type_Used_As_Initializer);
new(&buffer_[0]) T(val);
vptr_ = VTableImpl<T>::GetVPTR();
}
// Inter-Variant conversion constructor
// Current policy is: conversion succeeds iff the actual type of the source
// is one of the types accepted by the target
// @@@ Possible change: accept if the actual type of the source is
// convertible to one of the types accepted by the target. Problem to
// solve: handle ambiguities in a satisfactory manner. Suggestion: when
// in doubt, do closest to what the compiler would do.
template <class TList2, typename Align2>
void VariantConstruct(const Variant<TList2, Align2>& rhs, int)
{
typename Converter<Variant<TList2, Align2>, Variant>::Visitor v(*this);
typename Variant<TList2, Align2>::ConstStrictVisitor& visitor = v;
rhs.Accept(visitor);
}
public:
// VC7 don't support partial ordering
// The constructor initialization section
// is empty which make it to use function instead
// without the int = 0 the explicit seems to confuse
// VC7 when the copy constructor should be selected
// Crazy stuff
template <class T>
explicit Variant(const T& val, int = 0)
{
VariantConstruct(val, int(0));
}
// Canonic assignment operator
Variant& operator=(const Variant& rhs)
{
Private::SafeAssign(*this, rhs);
return *this;
}
private:
// Assignment operator from one of the allowed types
// This is necessary because the constructor is explicit
template <class T>
void VariantAssign(const T& rhs, double)
{
Private::SafeAssign(*this, rhs);
}
// Assignment from another Variant instantiation
template <class TList2, typename Align2>
void VariantAssign(const Variant<TList2, Align2>& rhs, int)
{
Private::SafeAssign(*this, rhs);
}
public:
// VC7 don't support partial ordering
template <class T>
Variant& operator=(const T& rhs)
{
// Both VariantAssign are the same in this implementation
VariantAssign(rhs, int(0));
return *this;
}
// ~
~Variant()
{
(vptr_->destroy_)(*this);
}
// Visitors definitions
// @@@ Possible improvement: add defintions of visitor who return
// something else than void
typedef ::Loki::Visitor<TList, void> StrictVisitor;
typedef ::Loki::Visitor<typename MakeConst<TList>::Result, void>
ConstStrictVisitor;
typedef ::Loki::NonStrictVisitor<TList, void> NonStrictVisitor;
typedef ::Loki::NonStrictVisitor<typename MakeConst<TList>::Result, void>
ConstNonStrictVisitor;
private:
// VTable structure
// The essential component of the fake vtable idiom, VTable contains
// pointers to functions, pointers that will be filled up with addresses
// of functions in VTableImpl
struct VTable
{
const std::type_info& (*typeId_)();
void (*destroy_)(const Variant&);
void (*clone_)(const Variant&, Variant&);
void (*swap_)(void* lhs, void* rhs);
void (*accept_)(Variant&, StrictVisitor&);
void (*acceptConst_)(const Variant&, ConstStrictVisitor&);
};
// VTable concrete implementations
// VTableImpl<T> contains definitions for all of a VTable's pointer to
// functions.
// VC7 thinks that Variant inside VTableImpl is template
typedef Variant VariantType;
template <class T>
struct VTableImpl
{
private:
static const std::type_info& TypeId()
{
return typeid(T);
}
static void Destroy(const VariantType& var)
{
const T& data = *reinterpret_cast<const T*>(&var.buffer_[0]);
(void)data.~T();
}
static void Swap(void* lhs, void* rhs)
{
Private::SwapHelper(*static_cast<T*>(lhs), *static_cast<T*>(rhs));
}
static void Clone(const VariantType& src, VariantType& dest)
{
new(&dest.buffer_[0]) T(
*reinterpret_cast<const T*>(&src.buffer_[0]));
dest.vptr_ = src.vptr_;
}
static void Accept(VariantType& var, StrictVisitor& visitor)
{
typedef typename StrictVisitor::ReturnType RType;
::Loki::Visitor<T,RType> &v = visitor;
v.Visit(*reinterpret_cast<T*>(&var.buffer_[0]));
}
static void AcceptConst(const VariantType& var, ConstStrictVisitor& visitor)
{
typedef typename ConstStrictVisitor::ReturnType RType;
::Loki::Visitor<const T,RType> &v = visitor;
v.Visit(*reinterpret_cast<const T*>(&var.buffer_[0]));
}
public:
static const VTable *GetVPTR()
{
static const VTable vTbl_ =
{
&TypeId,
&Destroy,
&Clone,
&Swap,
&Accept,
&AcceptConst,
};
return &vTbl_;
}
};
template <class T> friend struct VTableImpl;
private: // should be private; some compilers prefer 'public' :o}
enum { neededSize = MaxSize<TList>::result };
VTable const * vptr_;
union
{
Align dummy_;
char buffer_[neededSize];
};
public:
void swap(Variant& rhs)
{
if (this->TypeId() == rhs.TypeId())
{
(vptr_->swap_)(this->buffer_, rhs.buffer_);
}
else
{
Private::SafeSwap(*this, rhs);
}
}
const std::type_info& TypeId() const
{
return (vptr_->typeId_)();
}
template <typename T> T* GetPtr()
{
return TypeId() == typeid(T)
? reinterpret_cast<T*>(&buffer_[0])
: 0;
}
template <typename T> const T* GetPtr() const
{
return TypeId() == typeid(T)
? reinterpret_cast<const T*>(&buffer_[0])
: 0;
}
template <typename T> T& Get()
{
T* p = GetPtr<T>();
if (!p) throw std::runtime_error("Variant::Get() Invalid variant type");
return *p;
}
template <typename T> const T& Get() const
{
const T* p = GetPtr<T>();
if (!p) throw std::runtime_error("Variant::Get() const Invalid variant type");
return *p;
}
// Visitation primitives
// Although there are four visitor types, only two Accept functions are
// necessary, because the non-strict visitors inherit the strict visitors
void Accept(StrictVisitor& visitor)
{
(vptr_->accept_)(*this, visitor);
}
void Accept(ConstStrictVisitor& visitor) const
{
(vptr_->acceptConst_)(*this, visitor);
}
// Extracts the value of a Variant converted to a specific type
template <class To> To ConvertTo() const
{
typename ConverterTo<Variant, To>::Visitor v;
ConstStrictVisitor& visitor = v;
this->Accept(visitor);
return v.GetDestination();
}
// Changes the type of a Variant in-place
template <class To> void ChangeType()
{
Variant(this->ConvertTo<To>()).swap(*this);
}
};
////////////////////////////////////////////////////////////////////////////////
// Change log:
// July 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif

328
MSVC/1300/Visitor.h Normal file
View file

@ -0,0 +1,328 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: May 19, 2002
#ifndef VISITOR_INC_
#define VISITOR_INC_
#include "Typelist.h"
#include "HierarchyGenerators.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitor
// The base class of any Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
////////////////////////////////////////////////////////////////////////////////
// class template Visitor
// Forward decleration
////////////////////////////////////////////////////////////////////////////////
template <class T, typename R = void>
class Visitor;
namespace Private
{
// for some reason VC7 needs the base definition altough not in use
template <typename TListTag>
struct VisitorHelper1
{
template <typename T, typename R>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <typename TListTag>
struct VisitorHelper2
{
template <typename T, typename R>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct VisitorHelper1<TL::Typelist_tag>
{
template <class TList, typename R>
struct In
{
typedef Visitor<typename TList::Head, R> Result;
};
};
template <>
struct VisitorHelper2<TL::Typelist_tag>
{
template <class TList, typename R>
struct In
{
private:
template<typename Tail>
struct In1
{
typedef Visitor<typename TList::Tail, R> Result;
};
template<>
struct In1<NullType>
{
struct Result {};
};
public:
typedef typename In1<typename TList::Tail>::Result Result;
};
};
template <>
struct VisitorHelper1<TL::NoneList_tag>
{
template <class T, typename R>
struct In
{
struct Result
{
typedef R ReturnType;
virtual ReturnType Visit(T&) = 0;
};
};
};
template <>
struct VisitorHelper2<TL::NoneList_tag>
{
template <class T, typename R>
struct In { struct Result {}; };
};
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template Visitor
// The building block of Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
template <class T, typename R>
class Visitor
: public Private::VisitorHelper1
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, R>::Result
, public Private::VisitorHelper2
<
typename TL::is_Typelist<T>::type_tag
>
::template In<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 = void>
class BaseVisitorImpl;
namespace Private
{
// for some reason VC7 needs the base definition altough not in use
template<typename TListTag>
struct BaseVisitorImplHelper
{
template <typename T, typename R>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::Typelist_tag>
{
template <typename TList, typename R>
struct In
{
typedef BaseVisitorImpl<TList, R> Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::NullType_tag>
{
template <typename TList, typename R>
struct In
{
struct Result {};
};
};
} // namespace Private
template <class TList, typename R>
class BaseVisitorImpl
: public Visitor<typename TList::Head, R>
, public Private::BaseVisitorImplHelper
<
typename TL::is_Typelist<typename TList::Tail>::type_tag
>
::template In<typename TList::Tail, R>::Result
{
ASSERT_TYPELIST(TList);
public:
// using BaseVisitorImpl<Tail, R>::Visit;
virtual R Visit(typename TList::Head&)
{ return R(); }
};
////////////////////////////////////////////////////////////////////////////////
// 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();
}
};
template <class TList, typename R = void>
class NonStrictVisitor
: public GenLinearHierarchy<
TList,
NonStrictVisitorUnit,
Visitor<TList, R> >
{
};
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitable
////////////////////////////////////////////////////////////////////////////////
template <typename R, typename Visited>
struct DefaultCatchAll
{
static R OnUnknownVisitor(Visited&, BaseVisitor&)
{ return R(); }
};
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitable
////////////////////////////////////////////////////////////////////////////////
template
<
typename R = void,
template <typename, class> class CatchAll = DefaultCatchAll
>
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)
{
// Apply the Acyclic Visitor
if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
{
return p->Visit(visited);
}
return CatchAll<R, T>::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); }
////////////////////////////////////////////////////////////////////////////////
// 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;
virtual ~CyclicVisitor() {}
template <class Visited>
ReturnType GenericVisit(Visited& host)
{
Visitor<Visited, ReturnType>& subObj = *this;
return 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); }
} // 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!!!
////////////////////////////////////////////////////////////////////////////////
#endif // VISITOR_INC_

View file

@ -1,3 +1 @@
MSVC7 Rani Sharoni
Jonathan H. Lundquist
Shannon G. Barber (aka Magmai Kai Holmlor)

18
MSVC/1300/readme.txt Normal file
View file

@ -0,0 +1,18 @@
Last update: May 19, 2002
Directions:
To use Loki, 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.
Compatibility:
This is ported version of Loki to VC.NET (VC7 - 9466) it is only targeted for this compiler.
To compile your sources with the original Loki you'll have to place it in a separate directory.
More info:
http://moderncppdesign.com
http://www.geocities.com/rani_sharoni/LokiPort.html

View file

@ -24,8 +24,14 @@ namespace Loki
// Helper structure for the STATIC_CHECK macro // Helper structure for the STATIC_CHECK macro
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<int> struct CompileTimeError; template<bool CompileTimeAssertion>
template<> struct CompileTimeError<true> {}; struct CompileTimeError;
template<>
struct CompileTimeError<true>
{
typedef void type;
};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -38,14 +44,14 @@ namespace Loki
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define STATIC_CHECK(expr, msg) \ #define STATIC_CHECK(expr, msg) \
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } typedef char ERROR_##msg[1][(expr)]
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Change log: // Change log:
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun // March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
// definition // definition
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// July 09, 2002: improved for favor of VC diagnostic and usage
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif // STATIC_CHECK_INC_ #endif // STATIC_CHECK_INC_