move directory: MSVC->include/noncc

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@157 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
syntheticpp 2005-07-20 08:40:01 +00:00
parent 33e8c0a9d2
commit 339dcd4233
52 changed files with 22874 additions and 0 deletions

View file

@ -0,0 +1,167 @@
////////////////////////////////////////////////////////////////////////////////
// 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(U*& 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)
// September 25, 2004: Fixed bug in PrototypeFactoryUnit::GetPrototype, thanks
// to a bug report submitted by funcall.
////////////////////////////////////////////////////////////////////////////////
#endif // ABSTRACTFACTORY_INC_

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_

View file

@ -0,0 +1,231 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Data Generator by Mr. Shannon Barber
// This code DOES NOT accompany the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
//
// Code covered by the MIT License
//
// The author makes no representations about the suitability of this software
// for any purpose. It is provided "as is" without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 10, 2002
#pragma once
#include "Typelist.h"
//MSVC7 version
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template IterateTypes
////////////////////////////////////////////////////////////////////////////////
namespace TL
{
template<typename T>
struct nameof_type
{
const char* operator()()
{
return typeid(T).name();
}
};
template<typename T>
struct sizeof_type
{
size_t operator()()
{
return sizeof(T);
}
};
template <class TList, template <typename> class UnitFunc>
struct IterateTypes;
namespace Private
{
// for some reason VC7 needs the base definition altough not in use
template <typename TListTag>
struct IterateTypesHelper1
{
template <typename T, template <typename> class GenFunc>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <typename TListTag>
struct IterateTypesHelper2
{
template <typename T, template <typename> class GenFunc>
struct In
{
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct IterateTypesHelper1<TL::Typelist_tag>
{
template <class TList, template <typename> class GenFunc>
struct In
{
typedef IterateTypes<typename TList::Head, GenFunc> Result;
};
};
template <>
struct IterateTypesHelper2<TL::Typelist_tag>
{
template <class TList, template <typename> class GenFunc>
struct In
{
typedef IterateTypes<typename TList::Tail, GenFunc> Result;
};
};
template <>
struct IterateTypesHelper1<TL::NoneList_tag>
{
template <typename AtomicType, template <typename> class GenFunc>
struct In
{
struct Result
{
typedef GenFunc<AtomicType> genfunc_t;
template<class II>
void operator()(II ii)
{
genfunc_t gen;
//warning C4267: 'argument' : conversion from 'size_t' to 'const std::_Vbase', possible loss of data
#pragma warning(push)
#pragma warning(disable: 4267)
//TODOSGB
*ii = gen();
#pragma warning(pop)
++ii;
}
template<class II, class P1>
void operator()(II ii, P1 p1)
{
genfunc_t gen;
*ii = gen(p1);
++ii;
}
};
};
};
template <>
struct IterateTypesHelper2<TL::NoneList_tag>
{
template <typename AtomicType, template <typename> class GenFunc>
struct In
{
struct Result
{
template<class II> void operator()(II) {}
template<class II, class P1> void operator()(II, P1) {}
};
};
};
template <>
struct IterateTypesHelper1<TL::NullType_tag>
{
template <class TList, template <typename> class GenFunc>
struct In
{
struct Result
{
template<class II> void operator()(II) {}
template<class II, class P1> void operator()(II, P1) {}
};
};
};
template <>
struct IterateTypesHelper2<TL::NullType_tag>
{
template <class TList, template <typename> class GenFunc>
struct In
{
struct Result
{
template<class II> void operator()(II) {}
template<class II, class P1> void operator()(II, P1) {}
};
};
};
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template IterateTypes
// Iteratates a Typelist, and invokes the ctor of GenFunc<T>
// for each type in the list, passing a functor along the way.
// The functor is designed to be an insertion iterator which GenFunc<T>
// can use to output information about the types in the list.
////////////////////////////////////////////////////////////////////////////////
template <typename T, template <typename> class GenFunc>
struct IterateTypes
{
public:
typedef typename Private::IterateTypesHelper1
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, GenFunc>::Result head_t;
typedef typename Private::IterateTypesHelper2
<
typename TL::is_Typelist<T>::type_tag
>
::template In<T, GenFunc>::Result tail_t;
head_t head;
tail_t tail;
template<class II>
void operator()(II ii)
{
this->head.operator()(ii);
this->tail.operator()(ii);
}
template<class II, class P1>
void operator()(II ii, P1 p1)
{
this->head.operator()(ii, p1);
this->tail.operator()(ii, p1);
}
};
//UnitFunc is really a template-template parameter, but MSVC7
// chokes on the correct defintion. Oddly enough, it works correctly
// with the 'undecorated' template parameter declaraion!
//template <class> class UnitFunc
template<typename Types, class UnitFunc, typename II>
void iterate_types(II ii)
{
Loki::TL::IterateTypes<Types, UnitFunc> it;
it(ii);
}
}//ns TL
}//ns Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// Aug 17, 2002: Ported to MSVC7 by Rani Sharoni
// Aug 18, 2002: Removed ctor(II), replaced with operator(II) Shannon Barber
// Oct 10, 2002: Changed II (insertion iterator) from pass-by-reference to pass-by-value
////////////////////////////////////////////////////////////////////////////////

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
include/noncc/MSVC/1300/Factory.h Executable 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_

1358
include/noncc/MSVC/1300/Functor.h Executable 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
<
IsSameType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
static ResultType& Do(H& obj)
{
RightBase& rightBase = obj;
return FieldHelper<i - 1>::template In<RightBase>::Do(rightBase);
}
};
};
template <>
struct FieldHelper<0>
{
template<class H>
struct In
{
private:
typedef typename H::TList::Head ElementType;
typedef typename H::template Rebind<ElementType>::Result UnitType;
enum { isConst = TypeTraits<H>::isConst };
typedef typename Select
<
isConst,
const typename H::LeftBase,
typename H::LeftBase
>
::Result LeftBase;
typedef typename Select
<
IsSameType<UnitType, TupleUnit<ElementType> >::value,
ElementType,
UnitType
>
::Result UnqualifiedResultType;
public:
typedef typename Select
<
isConst,
const UnqualifiedResultType,
UnqualifiedResultType
>
::Result ResultType;
static ResultType& Do(H& obj)
{
LeftBase& leftBase = obj;
return leftBase;
}
};
};
////////////////////////////////////////////////////////////////////////////////
// function template Field
// Accesses a field in an object of a type generated with GenScatterHierarchy
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
// i is the index of a type in the typelist used to generate H):
// Field<i>(obj)
// returns a reference to Unit<T>, where Unit is the template used to generate H
// and T is the i-th type in the typelist
////////////////////////////////////////////////////////////////////////////////
template <unsigned int i, class H>
typename FieldHelper<i>::template In<H>::ResultType&
Field(H& obj)
{
return FieldHelper<i>::template In<H>::Do(obj);
}
////////////////////////////////////////////////////////////////////////////////
// class template GenLinearHierarchy
// Generates a linear hierarchy starting from a typelist and a template
// Invocation (TList is a typelist, Model is a template of two args):
// GenLinearHierarchy<TList, Model, Root>
////////////////////////////////////////////////////////////////////////////////
template
<
class TList,
template <class AtomicType, class UnitBase> class Unit,
class Root = EmptyType
>
class GenLinearHierarchy;
namespace Private
{
template <typename TListTag>
struct GenLinearHierarchyHelper
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::Typelist_tag>
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
typedef Unit< Head, GenLinearHierarchy<Tail, Unit, Root> > Result;
};
};
template <>
struct GenLinearHierarchyHelper<TL::NullType_tag>
{
template<class TList, template <class, class> class Unit, class Root>
struct In
{
private:
typedef typename TList::Head Head;
public:
typedef Unit<Head, Root> Result;
};
};
} // namespace Private
template
<
class TList,
template <class AtomicType, class UnitBase> class Unit,
class Root
>
class GenLinearHierarchy
: public Private::GenLinearHierarchyHelper
<
typename TL::is_Typelist<typename TList::Tail>::type_tag
>
::template In<TList, Unit, Root>::Result
{
ASSERT_TYPELIST(TList); // TList must not be NullType
public:
typedef typename Private::GenLinearHierarchyHelper
<
typename TL::is_Typelist<typename TList::Tail>::type_tag
>
::template In<TList, Unit, Root>::Result LinBase;
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
////////////////////////////////////////////////////////////////////////////////
#endif // HIERARCHYGENERATORS_INC_
#ifdef _MSC_VER
#pragma warning( pop )
#endif // _MSC_VER

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 LOKITYPEINFO_INC_
#define LOKITYPEINFO_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 // LOKITYPEINFO_INC_

112
include/noncc/MSVC/1300/MinMax.h Executable 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_

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

@ -0,0 +1,44 @@
////////////////////////////////////////////////////////////////////////////////
// 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 NULLTYPE_INC_
#define NULLTYPE_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class NullType
// Used as a placeholder for "no type here"
// Useful as an end marker in typelists
////////////////////////////////////////////////////////////////////////////////
class NullType
{
public:
struct Head { private: Head(); };
struct Tail { private: Tail(); };
};
}
///////////////////////////////////////////////////////////////////////////////
// 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 // NULLTYPE_INC_

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 C_CALLING_CONVENTION_QUALIFIER 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)
////////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,442 @@
////////////////////////////////////////////////////////////////////////////////
// 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>
#ifdef _MSC_VER
#define C_CALLING_CONVENTION_QUALIFIER __cdecl
#else
#define C_CALLING_CONVENTION_QUALIFIER
#endif
namespace Loki
{
typedef void (C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)();
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 C_CALLING_CONVENTION_QUALIFIER 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*, atexit_pfn_t 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*, atexit_pfn_t 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_(); }
atexit_pfn_t 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, atexit_pfn_t 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*, atexit_pfn_t)
{}
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 PtrInstanceType s_pInstance;
static bool s_destroyed;
};
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<SingletonHolder>::Lock guard;
(void)guard;
if (!pInstance_())
{
if (destroyed_())
{
LifetimePolicy<T>::OnDeadReference();
destroyed_() = false;
}
pInstance_() = CreationPolicy<T>::Create();
LifetimePolicy<T>::ScheduleDestruction
(
pInstance_(),
&DestroySingleton
);
}
}
static void C_CALLING_CONVENTION_QUALIFIER 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_

View file

@ -0,0 +1,612 @@
////////////////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////////////////
// $Header$
#include "SmallObj.h"
#include <cassert>
#include <vector>
#include <algorithm>
#include <functional>
using namespace Loki;
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class FixedAllocator
// Offers services for allocating fixed-sized objects
////////////////////////////////////////////////////////////////////////////////
class FixedAllocator
{
private:
struct Chunk
{
bool 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();
inline bool HasBlock( unsigned char * p, std::size_t chunkLength ) const
{ return ( pData_ <= p ) && ( p < pData_ + chunkLength ); }
inline bool HasAvailable( unsigned char numBlocks ) const
{ return ( blocksAvailable_ == numBlocks ); }
inline bool IsFilled( void ) const
{ return ( 0 == blocksAvailable_ ); }
unsigned char* pData_;
unsigned char
firstAvailableBlock_,
blocksAvailable_;
};
// Internal functions
void DoDeallocate(void* p);
bool MakeNewChunk( void );
Chunk * VicinityFind( void * p );
/// Not implemented.
FixedAllocator(const FixedAllocator&);
/// Not implemented.
FixedAllocator& operator=(const FixedAllocator&);
// Data
std::size_t blockSize_;
unsigned char numBlocks_;
typedef std::vector<Chunk> Chunks;
typedef Chunks::iterator ChunkIter;
typedef Chunks::const_iterator ChunkCIter;
Chunks chunks_;
Chunk* allocChunk_;
Chunk* deallocChunk_;
Chunk * emptyChunk_;
public:
// Create a FixedAllocator able to manage blocks of 'blockSize' size
FixedAllocator();
~FixedAllocator();
void Initialize( std::size_t blockSize, std::size_t pageSize );
// Allocate a memory block
void * Allocate( void );
// Deallocate a memory block previously allocated with Allocate()
// (if that's not the case, the behavior is undefined)
bool Deallocate( void * p, bool doChecks );
// Returns the block size with which the FixedAllocator was initialized
inline std::size_t BlockSize() const
{ return blockSize_; }
};
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Init
// Initializes a chunk object
////////////////////////////////////////////////////////////////////////////////
bool FixedAllocator::Chunk::Init( std::size_t blockSize, unsigned char blocks )
{
assert(blockSize > 0);
assert(blocks > 0);
// Overflow check
const std::size_t allocSize = blockSize * blocks;
assert( allocSize / blockSize == blocks);
#ifdef USE_NEW_TO_ALLOCATE
// If this new operator fails, it will throw, and the exception will get
// caught one layer up.
pData_ = new unsigned char[ allocSize ];
#else
// malloc can't throw, so its only way to indicate an error is to return
// a NULL pointer, so we have to check for that.
pData_ = static_cast< unsigned char * >( ::malloc( allocSize ) );
if ( NULL == pData_ ) return false;
#endif
Reset( blockSize, blocks );
return true;
}
////////////////////////////////////////////////////////////////////////////////
// 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()
{
assert( NULL != pData_ );
#ifdef USE_NEW_TO_ALLOCATE
delete [] pData_;
#else
::free( static_cast< void * >( pData_ ) );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Chunk::Allocate
// Allocates a block from a chunk
////////////////////////////////////////////////////////////////////////////////
void* FixedAllocator::Chunk::Allocate(std::size_t blockSize)
{
if ( IsFilled() ) return NULL;
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()
: blockSize_( 0 )
, allocChunk_( NULL )
, deallocChunk_( NULL )
, emptyChunk_( NULL )
{
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::~FixedAllocator
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::~FixedAllocator()
{
for ( ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i )
i->Release();
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Initialize
// Initializes the operational constraints for the FixedAllocator
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize )
{
assert( blockSize > 0 );
assert( pageSize >= blockSize );
blockSize_ = blockSize;
std::size_t numBlocks = pageSize / blockSize;
if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX;
else if ( numBlocks < 8 ) numBlocks = 8;
numBlocks_ = static_cast<unsigned char>(numBlocks);
assert(numBlocks_ == numBlocks);
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::MakeNewChunk
// Allocates a new Chunk for a FixedAllocator.
////////////////////////////////////////////////////////////////////////////////
bool FixedAllocator::MakeNewChunk( void )
{
bool allocated = false;
try
{
// Calling chunks_.reserve *before* creating and initializing the new
// Chunk means that nothing is leaked by this function in case an
// exception is thrown from reserve.
chunks_.reserve( chunks_.size() + 1 );
Chunk newChunk;
allocated = newChunk.Init( blockSize_, numBlocks_ );
if ( allocated )
chunks_.push_back( newChunk );
}
catch ( ... )
{
allocated = false;
}
if ( !allocated ) return false;
allocChunk_ = &chunks_.back();
deallocChunk_ = &chunks_.front();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Allocate
// Allocates a block of fixed size
////////////////////////////////////////////////////////////////////////////////
void * FixedAllocator::Allocate( void )
{
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() )
{
if ( NULL != emptyChunk_ )
{
allocChunk_ = emptyChunk_;
emptyChunk_ = NULL;
}
else
{
for ( ChunkIter i( chunks_.begin() ); ; ++i )
{
if ( chunks_.end() == i )
{
if ( !MakeNewChunk() )
return NULL;
break;
}
if ( !i->IsFilled() )
{
allocChunk_ = &*i;
break;
}
}
}
}
else if ( allocChunk_ == emptyChunk_)
// detach emptyChunk_ from allocChunk_, because after
// calling allocChunk_->Allocate(blockSize_); the chunk
// isn't any more empty
emptyChunk_ = NULL;
assert( allocChunk_ != NULL );
assert( !allocChunk_->IsFilled() );
void *place = allocChunk_->Allocate(blockSize_);
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
return place;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::Deallocate
// Deallocates a block previously allocated with Allocate
// (undefined behavior if called with the wrong pointer)
////////////////////////////////////////////////////////////////////////////////
bool FixedAllocator::Deallocate( void * p, bool doChecks )
{
if ( doChecks )
{
assert(!chunks_.empty());
assert(&chunks_.front() <= deallocChunk_);
assert(&chunks_.back() >= deallocChunk_);
assert( &chunks_.front() <= allocChunk_ );
assert( &chunks_.back() >= allocChunk_ );
}
Chunk * foundChunk = VicinityFind( p );
if ( doChecks )
{
assert( NULL != foundChunk );
}
else if ( NULL == foundChunk )
return false;
deallocChunk_ = foundChunk;
DoDeallocate(p);
return true;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::VicinityFind (internal)
// Finds the chunk corresponding to a pointer, using an efficient search
////////////////////////////////////////////////////////////////////////////////
FixedAllocator::Chunk * FixedAllocator::VicinityFind( void * p )
{
if ( chunks_.empty() ) return NULL;
assert(deallocChunk_);
unsigned char * pc = static_cast< unsigned char * >( p );
const std::size_t chunkLength = numBlocks_ * blockSize_;
Chunk* lo = deallocChunk_;
Chunk* hi = deallocChunk_ + 1;
Chunk* loBound = &chunks_.front();
Chunk* hiBound = &chunks_.back() + 1;
// Special case: deallocChunk_ is the last in the array
if (hi == hiBound) hi = NULL;
for (;;)
{
if (lo)
{
if ( lo->HasBlock( pc, chunkLength ) ) return lo;
if ( lo == loBound )
{
lo = NULL;
if ( NULL == hi ) break;
}
else --lo;
}
if (hi)
{
if ( hi->HasBlock( pc, chunkLength ) ) return hi;
if ( ++hi == hiBound )
{
hi = NULL;
if ( NULL == lo ) break;
}
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
// FixedAllocator::DoDeallocate (internal)
// Performs deallocation. Assumes deallocChunk_ points to the correct chunk
////////////////////////////////////////////////////////////////////////////////
void FixedAllocator::DoDeallocate(void* p)
{
assert( deallocChunk_->HasBlock( static_cast< unsigned char * >( p ),
numBlocks_ * blockSize_ ) );
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
// call into the chunk, will adjust the inner list but won't release memory
deallocChunk_->Deallocate(p, blockSize_);
if ( deallocChunk_->HasAvailable( numBlocks_ ) )
{
assert( emptyChunk_ != deallocChunk_ );
// deallocChunk_ is empty, but a Chunk is only released if there are 2
// empty chunks. Since emptyChunk_ may only point to a previously
// cleared Chunk, if it points to something else besides deallocChunk_,
// then FixedAllocator currently has 2 empty Chunks.
if ( NULL != emptyChunk_ )
{
// If last Chunk is empty, just change what deallocChunk_
// points to, and release the last. Otherwise, swap an empty
// Chunk with the last, and then release it.
Chunk * lastChunk = &chunks_.back();
if ( lastChunk == deallocChunk_ )
deallocChunk_ = emptyChunk_;
else if ( lastChunk != emptyChunk_ )
std::swap( *emptyChunk_, *lastChunk );
assert( lastChunk->HasAvailable( numBlocks_ ) );
lastChunk->Release();
chunks_.pop_back();
allocChunk_ = deallocChunk_;
}
emptyChunk_ = deallocChunk_;
}
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
}
////////////////////////////////////////////////////////////////////////////////
// GetOffset
// Calculates index into array where a FixedAllocator of numBytes is located.
////////////////////////////////////////////////////////////////////////////////
inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment )
{
const std::size_t alignExtra = alignment-1;
return ( numBytes + alignExtra ) / alignment;
}
////////////////////////////////////////////////////////////////////////////////
// DefaultAllocator
// Call to default allocator when SmallObjAllocator decides not to handle request.
////////////////////////////////////////////////////////////////////////////////
void * DefaultAllocator( std::size_t numBytes, bool doThrow )
{
#ifdef USE_NEW_TO_ALLOCATE
return doThrow ? ::operator new( numBytes ) :
::operator new( numBytes, std::nothrow_t() );
#else
void * p = ::malloc( numBytes );
if ( doThrow && ( NULL == p ) )
throw std::bad_alloc();
return p;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// DefaultDeallocator
// Call to default deallocator when SmallObjAllocator decides not to handle request.
////////////////////////////////////////////////////////////////////////////////
void DefaultDeallocator( void * p )
{
#ifdef USE_NEW_TO_ALLOCATE
::operator delete( p );
#else
::free( p );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::SmallObjAllocator
// Creates a SmallObjAllocator, and all the FixedAllocators within it. Each
// FixedAllocator is then initialized to use the correct Chunk size.
////////////////////////////////////////////////////////////////////////////////
SmallObjAllocator::SmallObjAllocator( std::size_t pageSize,
std::size_t maxObjectSize, std::size_t objectAlignSize ) :
pool_( NULL ),
maxSmallObjectSize_( maxObjectSize ),
objectAlignSize_( objectAlignSize )
{
assert( 0 != objectAlignSize );
const std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize );
pool_ = new FixedAllocator[ allocCount ];
for ( std::size_t i = 0; i < allocCount; ++i )
pool_[ i ].Initialize( ( i+1 ) * objectAlignSize, pageSize );
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::~SmallObjAllocator
// Deletes all memory consumed by SmallObjAllocator.
// This deletes all the FixedAllocator's in the pool.
////////////////////////////////////////////////////////////////////////////////
SmallObjAllocator::~SmallObjAllocator( void )
{
delete [] pool_;
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::Allocate
// Handles request to allocate numBytes for 1 object.
// This acts in constant-time - except for the calls to DefaultAllocator
// and sometimes FixedAllocator::Allocate. It throws bad_alloc only if the
// doThrow parameter is true and can't allocate another block. Otherwise, it
// provides the no-throw exception safety level.
////////////////////////////////////////////////////////////////////////////////
void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
{
if ( numBytes > GetMaxObjectSize() )
return DefaultAllocator( numBytes, doThrow );
assert( NULL != pool_ );
if ( 0 == numBytes ) numBytes = 1;
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
assert( index < allocCount );
FixedAllocator & allocator = pool_[ index ];
assert( allocator.BlockSize() >= numBytes );
assert( allocator.BlockSize() < numBytes + GetAlignment() );
void * place = allocator.Allocate();
if ( ( NULL == place ) && doThrow )
{
#if _MSC_VER
throw std::bad_alloc( "could not allocate small object" );
#else
// GCC did not like a literal string passed to std::bad_alloc.
// so just throw the default-constructed exception.
throw std::bad_alloc();
#endif
}
return place;
}
////////////////////////////////////////////////////////////////////////////////
// SmallObjAllocator::Deallocate
// Handles request to deallocate numBytes for 1 object.
// This will act in constant-time - except for the calls to DefaultDeallocator
// and sometimes FixedAllocator::Deallocate. It will never throw.
////////////////////////////////////////////////////////////////////////////////
void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
{
if ( NULL == p ) return;
if ( numBytes > GetMaxObjectSize() )
{
DefaultDeallocator( p );
return;
}
assert( NULL != pool_ );
if ( 0 == numBytes ) numBytes = 1;
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
assert( index < allocCount );
FixedAllocator & allocator = pool_[ index ];
assert( allocator.BlockSize() >= numBytes );
assert( allocator.BlockSize() < numBytes + GetAlignment() );
const bool found = allocator.Deallocate( p, true );
assert( found );
}
}; // end namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// March 20: fix exception safety issue in FixedAllocator::Allocate
// (thanks to Chris Udazvinis for pointing that out)
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Aug 02, 2002: Fix in VicinityFind sent by Pavel Vozenilek
// Nov 26, 2004: Re-implemented by Rich Sposato.
// Jun 22, 2005: Fix in FixedAllocator::Allocate by Chad Lehman
////////////////////////////////////////////////////////////////////////////////
// $Log$
// Revision 1.1 2005/07/20 08:40:01 syntheticpp
// move directory: MSVC->include/noncc
//
// Revision 1.9 2005/07/20 00:34:15 rich_sposato
// Fixed overflow bug in calculating number of blocks per Chunk.
//

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-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: Nov 26, 2004
#ifndef SMALLOBJ_INC_
#define SMALLOBJ_INC_
#include "Threads.h"
#include "Singleton.h"
#include <cstddef>
#include <new> // needed for std::nothrow_t parameter.
#ifndef DEFAULT_CHUNK_SIZE
#define DEFAULT_CHUNK_SIZE 4096
#endif
#ifndef MAX_SMALL_OBJECT_SIZE
#define MAX_SMALL_OBJECT_SIZE 256
#endif
#ifndef LOKI_DEFAULT_OBJECT_ALIGNMENT
#define LOKI_DEFAULT_OBJECT_ALIGNMENT 4
#endif
namespace Loki
{
class FixedAllocator;
class SmallObjAllocator
{
public:
SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize,
std::size_t objectAlignSize );
~SmallObjAllocator( void );
void * Allocate( std::size_t size, bool doThrow );
void Deallocate( void * p, std::size_t size );
inline std::size_t GetMaxObjectSize() const { return maxSmallObjectSize_; }
inline std::size_t GetAlignment() const { return objectAlignSize_; }
private:
Loki::FixedAllocator * pool_;
std::size_t maxSmallObjectSize_;
std::size_t objectAlignSize_;
};
////////////////////////////////////////////////////////////////////////////////
// class SmallObject
// Base class for polymorphic small objects, offers fast allocations &
// deallocations. Destructor is virtual and public.
////////////////////////////////////////////////////////////////////////////////
template
<
template <class> class ThreadingModel = DEFAULT_THREADING,
std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE,
std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT
>
class SmallObject : public ThreadingModel<
SmallObject< ThreadingModel, chunkSize, maxSmallObjectSize, objectAlignSize > >
{
typedef ThreadingModel< SmallObject<ThreadingModel,
chunkSize, maxSmallObjectSize, objectAlignSize > > MyThreadingModel;
struct MySmallObjAllocator : public SmallObjAllocator
{
MySmallObjAllocator()
: SmallObjAllocator( chunkSize, maxSmallObjectSize, objectAlignSize )
{}
};
// The typedef below would make things much simpler,
// but MWCW won't like it
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
// NoDestroy, ThreadingModel*/> MyAllocator;
public:
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0) && (LOKI_DEFAULT_OBJECT_ALIGNMENT != 0)
/// Throwing single-object new.
static void * operator new ( std::size_t size ) throw ( std::bad_alloc )
{
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
return SingletonHolder< MySmallObjAllocator, CreateStatic,
NoDestroy >::Instance().Allocate( size, true );
}
/// Non-throwing single-object new.
static void * operator new ( std::size_t size, const std::nothrow_t & ) throw ()
{
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
return SingletonHolder< MySmallObjAllocator, CreateStatic,
NoDestroy >::Instance().Allocate( size, false );
}
/// Placement single-object new.
static void * operator new ( std::size_t size, void * place )
{
return ::operator new( size, place );
}
/// Single-object delete.
static void operator delete ( void * p, std::size_t size ) throw ()
{
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
SingletonHolder< MySmallObjAllocator, CreateStatic,
NoDestroy >::Instance().Deallocate( p, size );
}
/// Non-throwing single-object delete.
static void operator delete ( void * p, std::size_t size,
const std::nothrow_t & ) throw()
{
typename MyThreadingModel::Lock lock;
(void)lock; // get rid of warning
SingletonHolder< MySmallObjAllocator, CreateStatic,
NoDestroy >::Instance().Deallocate( p, size );
}
/// Placement single-object delete.
static void operator delete ( void * p, void * place )
{
::operator delete ( p, place );
}
#endif // #if default template parameters are not zero
virtual ~SmallObject() {}
}; // end class SmallObject
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// Nov. 26, 2004: re-implemented by Rich Sposato.
////////////////////////////////////////////////////////////////////////////////
#endif // SMALLOBJ_INC_

1331
include/noncc/MSVC/1300/SmartPtr.h Executable file

File diff suppressed because it is too large Load diff

199
include/noncc/MSVC/1300/Threads.h Executable file
View file

@ -0,0 +1,199 @@
#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 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
{
mutable CRITICAL_SECTION mtx_;
public:
ObjectLevelLockable()
{
::InitializeCriticalSection(&mtx_);
}
~ObjectLevelLockable()
{
::DeleteCriticalSection(&mtx_);
}
class Lock;
friend class Lock;
class Lock
{
ObjectLevelLockable const& host_;
Lock(const Lock&);
Lock& operator=(const Lock&);
public:
explicit Lock(const 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(const 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

@ -0,0 +1,245 @@
////////////////////////////////////////////////////////////////////////////////
// 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 TYPEMANIP_INC_
#define TYPEMANIP_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template Int2Type
// Converts each integral constant into a unique type
// Invocation: Int2Type<v> where v is a compile-time constant integral
// Defines 'value', an enum that evaluates to v
////////////////////////////////////////////////////////////////////////////////
template <int v>
struct Int2Type
{
enum { value = v };
};
////////////////////////////////////////////////////////////////////////////////
// class template Type2Type
// Converts each type into a unique, insipid type
// Invocation Type2Type<T> where T is a type
// Defines the type OriginalType which maps back to T
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct Type2Type
{
typedef T OriginalType;
Type2Type(){} // VC7
};
////////////////////////////////////////////////////////////////////////////////
// class template Select
// Selects one of two types based upon a boolean constant
// Invocation: Select<flag, T, U>::Result
// where:
// flag is a compile-time boolean constant
// T and U are types
// Result evaluates to T if flag is true, and to U otherwise.
////////////////////////////////////////////////////////////////////////////////
template <bool flag, typename T, typename U>
struct Select
{
private:
template<bool>
struct In
{ typedef T Result; };
template<>
struct In<false>
{ typedef U Result; };
public:
typedef typename In<flag>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template IsSameType
// Return true iff two given types are the same
// Invocation: IsSameType<T, U>::value
// where:
// T and U are types
// Result evaluates to true iff U == T (types equal)
////////////////////////////////////////////////////////////////////////////////
template <typename T, typename U>
struct IsSameType
{
private:
template<typename>
struct In
{ enum { value = false }; };
template<>
struct In<T>
{ enum { value = true }; };
public:
enum { value = In<U>::value };
};
////////////////////////////////////////////////////////////////////////////////
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
typedef char Small;
class Big { char dummy[2]; };
template<typename T>
struct IsVoid
{
enum { result =
IsSameType<T, void>::value ||
IsSameType<T, const void>::value ||
IsSameType<T, volatile void>::value ||
IsSameType<T, const volatile void>::value
};
};
}
//
// is one type convertable to another?
//
template <class T, class U>
class is_convertible
{
struct VoidReplace {};
typedef typename Select
<
Private::IsVoid<T>::result,
VoidReplace, T
>
::Result T1;
typedef typename Select
<
Private::IsVoid<U>::result,
VoidReplace, U
>
::Result U1;
static Private::Big Test(...);
static Private::Small Test(U1);
static T1 MakeT();
public:
enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
};
////////////////////////////////////////////////////////////////////////////////
// class template Conversion
// Figures out the conversion relationships between two types
// Invocations (T and U are types):
// a) Conversion<T, U>::exists
// returns (at compile time) true if there is an implicit conversion from T
// to U (example: Derived to Base)
// b) Conversion<T, U>::exists2Way
// returns (at compile time) true if there are both conversions from T
// to U and from U to T (example: int to char and back)
// c) Conversion<T, U>::sameType
// returns (at compile time) true if T and U represent the same type
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct Conversion
{
enum { exists = (is_convertible<T,U>::exists) };
enum { exists2Way = (exists && is_convertible<U, T>::exists) };
enum { sameType = (IsSameType<T, U>::value) };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclass
// Invocation: SuperSubclass<B, D>::value where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct SuperSubclass
{
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclassStrict
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template<class T,class U>
struct SuperSubclassStrict
{
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
!::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclass class template instead.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS(T, U) \
::Loki::SuperSubclass<T,U>::value
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS_STRICT
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclassStrict class template instead.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS_STRICT(T, U) \
::Loki::SuperSubclassStrict<T,U>::value
////////////////////////////////////////////////////////////////////////////////
// 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)
// October 10, 2002: Commented IsSameType template (not a Loki-template - yet). MKH
// October 12, 2002: Added SuperSubclass and SuperSubclassStrict templates.
// The corresponding macros are deprecated. T.S.
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEMANIP_INC_

View file

@ -0,0 +1,370 @@
////////////////////////////////////////////////////////////////////////////////
// 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
//TODOSGB None of the parameter types are defined inside of TypeTraits, e.g. PointeeType, ReferredType, etc...
#ifndef TYPETRAITS_INC_
#define TYPETRAITS_INC_
#include "Typelist.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomUnsignedInt
// Offers a means to integrate nonstandard built-in unsigned integral types
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
// class template defined below.
// Invocation: IsCustomUnsignedInt<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
// integral type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomUnsignedInt
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomSignedInt
// Offers a means to integrate nonstandard built-in unsigned integral types
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
// class template defined below.
// Invocation: IsCustomSignedInt<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in signed
// integral type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomSignedInt
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// class template IsCustomFloat
// Offers a means to integrate nonstandard floating point types with the
// TypeTraits class template defined below.
// Invocation: IsCustomFloat<T> where T is any type
// Defines 'value', an enum that is 1 iff T is a custom built-in
// floating point type
// Specialize this class template for nonstandard unsigned integral types
// and define value = 1 in those specializations
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct IsCustomFloat
{
enum { value = 0 };
};
////////////////////////////////////////////////////////////////////////////////
// Helper types for class template TypeTraits defined below
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
typedef TYPELIST_4(unsigned char, unsigned short int,
unsigned int, unsigned long int) StdUnsignedInts;
typedef TYPELIST_4(signed char, short int,
int, long int) StdSignedInts;
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
typedef TYPELIST_3(float, double, long double) StdFloats;
}
namespace Private
{
template<typename T>
class IsArray
{
template <typename> struct Type2Type2 {};
typedef char (&yes)[1];
typedef char (&no) [2];
template<typename U, size_t N>
static void vc7_need_this_for_is_array(Type2Type2<U(*)[N]>);
template<typename U, size_t N>
static yes is_array1(Type2Type2<U[N]>*);
static no is_array1(...);
template<typename U>
static yes is_array2(Type2Type2<U[]>*);
static no is_array2(...);
public:
enum {
value =
sizeof(is_array1((Type2Type2<T>*)0)) == sizeof(yes) ||
sizeof(is_array2((Type2Type2<T>*)0)) == sizeof(yes)
};
};
} // Private Namespace
////////////////////////////////////////////////////////////////////////////////
// class template TypeTraits
// Figures out various properties of any given type
// Invocations (T is a type):
// a) TypeTraits<T>::isPointer
// returns (at compile time) true if T is a pointer type
// b) TypeTraits<T>::PointeeType
// returns the type to which T points is T is a pointer type, NullType otherwise
// a) TypeTraits<T>::isReference
// returns (at compile time) true if T is a reference type
// b) TypeTraits<T>::ReferredType
// returns the type to which T refers is T is a reference type, NullType
// otherwise
// c) TypeTraits<T>::isMemberPointer
// returns (at compile time) true if T is a pointer to member type
// d) TypeTraits<T>::isStdUnsignedInt
// returns (at compile time) true if T is a standard unsigned integral type
// e) TypeTraits<T>::isStdSignedInt
// returns (at compile time) true if T is a standard signed integral type
// f) TypeTraits<T>::isStdIntegral
// returns (at compile time) true if T is a standard integral type
// g) TypeTraits<T>::isStdFloat
// returns (at compile time) true if T is a standard floating-point type
// h) TypeTraits<T>::isStdArith
// returns (at compile time) true if T is a standard arithmetic type
// i) TypeTraits<T>::isStdFundamental
// returns (at compile time) true if T is a standard fundamental type
// j) TypeTraits<T>::isUnsignedInt
// returns (at compile time) true if T is a unsigned integral type
// k) TypeTraits<T>::isSignedInt
// returns (at compile time) true if T is a signed integral type
// l) TypeTraits<T>::isIntegral
// returns (at compile time) true if T is a integral type
// m) TypeTraits<T>::isFloat
// returns (at compile time) true if T is a floating-point type
// n) TypeTraits<T>::isArith
// returns (at compile time) true if T is a arithmetic type
// o) TypeTraits<T>::isFundamental
// returns (at compile time) true if T is a fundamental type
// p) TypeTraits<T>::ParameterType
// returns the optimal type to be used as a parameter for functions that take Ts
// q) TypeTraits<T>::isConst
// returns (at compile time) true if T is a const-qualified type
// r) TypeTraits<T>::NonConstType
// removes the 'const' qualifier from T, if any
// s) TypeTraits<T>::isVolatile
// returns (at compile time) true if T is a volatile-qualified type
// t) TypeTraits<T>::NonVolatileType
// removes the 'volatile' qualifier from T, if any
// u) TypeTraits<T>::UnqualifiedType
// removes both the 'const' and 'volatile' qualifiers from T, if any
////////////////////////////////////////////////////////////////////////////////
template <typename T>
class TypeTraits
{
typedef char (&yes)[1];
typedef char (&no) [2];
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>
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 reference to function
//
enum {
isReference =
sizeof(is_reference(Type2Type<T>())) == sizeof(yes)
};
//
// 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)
};
enum {
isMemberPointer =
sizeof(is_pointer2member(Type2Type<T>())) == sizeof(yes)
};
enum {
isArray = Private::IsArray<T>::value
};
enum {
isVoid =
IsSameType<T, void>::value ||
IsSameType<T, const void>::value ||
IsSameType<T, volatile void>::value ||
IsSameType<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 };
enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
enum { isArith = isIntegral || isFloat };
enum { isFundamental = isStdFundamental || isArith || isFloat };
enum {
isConst =
sizeof(is_const(Type2Type<T>())) == sizeof(yes)
};
enum {
isVolatile =
sizeof(is_volatile(Type2Type<T>())) == sizeof(yes)
};
private:
// is_scalar include functions types
struct is_scalar
{
private:
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:
// 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 // TYPETRAITS_INC_

1062
include/noncc/MSVC/1300/Typelist.h Executable file

File diff suppressed because it is too large Load diff

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
include/noncc/MSVC/1300/Variant.h Executable 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
include/noncc/MSVC/1300/Visitor.h Executable 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

@ -0,0 +1,2 @@
MSVC7
Rani Sharoni

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

@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////
// 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 STATIC_CHECK_INC_
#define STATIC_CHECK_INC_
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// Helper structure for the STATIC_CHECK macro
////////////////////////////////////////////////////////////////////////////////
template<bool CompileTimeAssertion>
struct CompileTimeError;
template<>
struct CompileTimeError<true>
{
typedef void type;
};
}
////////////////////////////////////////////////////////////////////////////////
// macro STATIC_CHECK
// Invocation: STATIC_CHECK(expr, id)
// where:
// expr is a compile-time integral or pointer expression
// id is a C++ identifier that does not need to be defined
// If expr is zero, id will appear in a compile-time error message.
////////////////////////////////////////////////////////////////////////////////
#define STATIC_CHECK(expr, msg) \
typedef char ERROR_##msg[1][(expr)]
////////////////////////////////////////////////////////////////////////////////
// Change log:
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
// definition
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// July 09, 2002: improved for favor of VC diagnostic and usage
////////////////////////////////////////////////////////////////////////////////
#endif // STATIC_CHECK_INC_