*** empty log message ***

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@85 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
tslettebo 2003-01-06 02:18:31 +00:00
parent 90a16ecbd4
commit 6539637357
11 changed files with 0 additions and 2899 deletions

View file

@ -1,335 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef ASSOCVECTOR_INC_
#define ASSOCVECTOR_INC_
#include <algorithm>
#include <functional>
#include <vector>
#include <utility>
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template AssocVectorCompare
// Used by AssocVector
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class Value, class C>
class AssocVectorCompare : public C
{
typedef std::pair<typename C::first_argument_type, Value>
Data;
typedef typename C::first_argument_type first_argument_type;
public:
AssocVectorCompare()
{}
AssocVectorCompare(const C& src) : C(src)
{}
bool operator()(const first_argument_type& lhs,
const first_argument_type& rhs) const
{ return C::operator()(lhs, rhs); }
bool operator()(const Data& lhs, const Data& rhs) const
{ return operator()(lhs.first, rhs.first); }
bool operator()(const Data& lhs,
const first_argument_type& rhs) const
{ return operator()(lhs.first, rhs); }
bool operator()(const first_argument_type& lhs,
const Data& rhs) const
{ return operator()(lhs, rhs.first); }
};
}
////////////////////////////////////////////////////////////////////////////////
// class template AssocVector
// An associative vector built as a syntactic drop-in replacement for std::map
// BEWARE: AssocVector doesn't respect all map's guarantees, the most important
// being:
// * iterators are invalidated by insert and erase operations
// * the complexity of insert/erase is O(N) not O(log N)
// * value_type is std::pair<K, V> not std::pair<const K, V>
// * iterators are random
////////////////////////////////////////////////////////////////////////////////
template
<
class K,
class V,
class C = std::less<K>,
class A = std::allocator< std::pair<K, V> >
>
class AssocVector
: private std::vector< std::pair<K, V>, A >
, private Private::AssocVectorCompare<V, C>
{
typedef std::vector<std::pair<K, V>, A> Base;
typedef Private::AssocVectorCompare<V, C> MyCompare;
public:
typedef K key_type;
typedef V mapped_type;
typedef typename Base::value_type value_type;
typedef C key_compare;
typedef A allocator_type;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename Base::reverse_iterator reverse_iterator;
typedef typename Base::const_reverse_iterator const_reverse_iterator;
class value_compare
: public std::binary_function<value_type, value_type, bool>
, private key_compare
{
friend class AssocVector;
protected:
value_compare(key_compare pred) : key_compare(pred)
{}
public:
bool operator()(const value_type& lhs, const value_type& rhs) const
{ return key_compare::operator()(lhs.first, rhs.first); }
};
// 23.3.1.1 construct/copy/destroy
explicit AssocVector(const key_compare& comp = key_compare(),
const A& alloc = A())
: Base(alloc), MyCompare(comp)
{}
template <class InputIterator>
AssocVector(InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const A& alloc = A())
: Base(first, last, alloc), MyCompare(comp)
{
MyCompare& me = *this;
std::sort(begin(), end(), me);
}
AssocVector& operator=(const AssocVector& rhs)
{
AssocVector(rhs).swap(*this);
return *this;
}
// iterators:
// The following are here because MWCW gets 'using' wrong
iterator begin() { return Base::begin(); }
const_iterator begin() const { return Base::begin(); }
iterator end() { return Base::end(); }
const_iterator end() const { return Base::end(); }
reverse_iterator rbegin() { return Base::rbegin(); }
const_reverse_iterator rbegin() const { return Base::rbegin(); }
reverse_iterator rend() { return Base::rend(); }
const_reverse_iterator rend() const { return Base::rend(); }
// capacity:
bool empty() const { return Base::empty(); }
size_type size() const { return Base::size(); }
size_type max_size() { return Base::max_size(); }
// 23.3.1.2 element access:
mapped_type& operator[](const key_type& key)
{ return insert(value_type(key, mapped_type())).first->second; }
// modifiers:
std::pair<iterator, bool> insert(const value_type& val)
{
bool found(true);
iterator i(lower_bound(val.first));
if (i == end() || operator()(val.first, i->first))
{
i = Base::insert(i, val);
found = false;
}
return std::make_pair(i, !found);
}
iterator insert(iterator pos, const value_type& val)
{
if (pos != end() && operator()(*pos, val) &&
(pos == end() - 1 ||
!operator()(val, pos[1]) &&
operator()(pos[1], val)))
{
return Base::insert(pos, val);
}
return insert(val).first;
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{ for (; first != last; ++first) insert(*first); }
void erase(iterator pos)
{ Base::erase(pos); }
size_type erase(const key_type& k)
{
iterator i(find(k));
if (i == end()) return 0;
erase(i);
return 1;
}
void erase(iterator first, iterator last)
{ Base::erase(first, last); }
void swap(AssocVector& other)
{
using std::swap;
Base::swap(other);
MyCompare& me = *this;
MyCompare& rhs = other;
swap(me, rhs);
}
void clear()
{ Base::clear(); }
// observers:
key_compare key_comp() const
{ return *this; }
value_compare value_comp() const
{
const key_compare& comp = *this;
return value_compare(comp);
}
// 23.3.1.3 map operations:
iterator find(const key_type& k)
{
iterator i(lower_bound(k));
if (i != end() && operator()(k, i->first))
{
i = end();
}
return i;
}
const_iterator find(const key_type& k) const
{
const_iterator i(lower_bound(k));
if (i != end() && operator()(k, i->first))
{
i = end();
}
return i;
}
size_type count(const key_type& k) const
{ return find(k) != end(); }
iterator lower_bound(const key_type& k)
{
MyCompare& me = *this;
return std::lower_bound(begin(), end(), k, me);
}
const_iterator lower_bound(const key_type& k) const
{
const MyCompare& me = *this;
return std::lower_bound(begin(), end(), k, me);
}
iterator upper_bound(const key_type& k)
{
MyCompare& me = *this;
return std::upper_bound(begin(), end(), k, me);
}
const_iterator upper_bound(const key_type& k) const
{
const MyCompare& me = *this;
return std::upper_bound(begin(), end(), k, me);
}
std::pair<iterator, iterator> equal_range(const key_type& k)
{
MyCompare& me = *this;
return std::equal_range(begin(), end(), k, me);
}
std::pair<const_iterator, const_iterator> equal_range(
const key_type& k) const
{
const MyCompare& me = *this;
return std::equal_range(begin(), end(), k, me);
}
friend bool operator==(const AssocVector& lhs, const AssocVector& rhs)
{
const Base& me = lhs;
return me == rhs;
}
bool operator<(const AssocVector& rhs) const
{
const Base& me = *this;
const Base& yo = rhs;
return me < yo;
}
friend bool operator!=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(lhs == rhs); }
friend bool operator>(const AssocVector& lhs, const AssocVector& rhs)
{ return rhs < lhs; }
friend bool operator>=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(lhs < rhs); }
friend bool operator<=(const AssocVector& lhs, const AssocVector& rhs)
{ return !(rhs < lhs); }
};
// specialized algorithms:
template <class K, class V, class C, class A>
void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
{ lhs.swap(rhs); }
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// May 20, 2001: change operator= - credit due to Cristoph Koegl
// June 11, 2001: remove paren in equal_range - credit due to Cristoph Koegl
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// January 22, 2002: fixed operator= - credit due to Tom Hyer
// June 25, 2002: fixed template insert() - credit due to Robert Minsk
// June 27, 2002: fixed member swap() - credit due to David Brookman
////////////////////////////////////////////////////////////////////////////////
#endif // ASSOCVECTOR_INC_

View file

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

View file

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

View file

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

View file

@ -1,53 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: June 20, 2001
#include "Singleton.h"
using namespace Loki::Private;
Loki::Private::TrackerArray Loki::Private::pTrackerArray = 0;
unsigned int Loki::Private::elements = 0;
////////////////////////////////////////////////////////////////////////////////
// function AtExitFn
// Ensures proper destruction of objects with longevity
////////////////////////////////////////////////////////////////////////////////
void Loki::Private::AtExitFn()
{
assert(elements > 0 && pTrackerArray != 0);
// Pick the element at the top of the stack
LifetimeTracker* pTop = pTrackerArray[elements - 1];
// Remove that object off the stack
// Don't check errors - realloc with less memory
// can't fail
pTrackerArray = static_cast<TrackerArray>(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!!!
// January 10, 2002: Fixed bug in call to realloc - credit due to Nigel Gent and
// Eike Petersen
// May 08, 2002: Refixed bug in call to realloc
// October 12, 2002: Ported to MSVC 6 by Terje Slettebø.
// Interface for SingletonHolder changed from using template template
// parameters, to using classes with member templates.
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,499 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// 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 SINGLETON_INC_
#define SINGLETON_INC_
#include "Threads.h"
#include <algorithm>
#include <stdexcept>
#include <cassert>
#include <cstdlib>
#include <new>
namespace Loki
{
namespace Private
{
template< typename T >
struct MSVCNeverTrue
{
enum { value = false };
};
template <class MetaFunctionWrapper, class T>
struct Apply
{
#ifdef _MSC_VER
// based on the (non-conforming) MSVC trick from MPL
template<bool>
struct MetaFunctionWrapper_VC : MetaFunctionWrapper {};
//illegal C++ which causes VC to admit that MetaFunctionWrapper_VC
//can have a nested template:
template<>
struct MetaFunctionWrapper_VC<true>
{template<class> struct VolatileType; };
typedef typename MetaFunctionWrapper_VC<
MSVCNeverTrue<MetaFunctionWrapper>::value
>::template VolatileType<T>::Result Result;
#else
typedef typename MetaFunctionWrapper::template VolatileType<T>::Result Result;
#endif
};
////////////////////////////////////////////////////////////////////////////////
// class LifetimeTracker
// Helper class for SetLongevity
////////////////////////////////////////////////////////////////////////////////
class LifetimeTracker
{
public:
LifetimeTracker(unsigned int x) : longevity_(x)
{}
virtual ~LifetimeTracker() = 0;
static bool Compare(const LifetimeTracker* lhs,
const LifetimeTracker* rhs)
{
return lhs->longevity_ > rhs->longevity_;
}
private:
unsigned int longevity_;
};
// Definition required
inline LifetimeTracker::~LifetimeTracker() {}
// Helper data
typedef LifetimeTracker** TrackerArray;
extern TrackerArray pTrackerArray;
extern unsigned int elements;
// Helper destroyer function
template <typename T>
struct Deleter
{
static void Delete(T* pObj)
{ delete pObj; }
};
// Concrete lifetime tracker for objects of type T
template <typename T, typename Destroyer>
class ConcreteLifetimeTracker : public LifetimeTracker
{
public:
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
: LifetimeTracker(longevity)
, pTracked_(p)
, destroyer_(d)
{}
~ConcreteLifetimeTracker()
{ destroyer_(pTracked_); }
private:
T* pTracked_;
Destroyer destroyer_;
};
void AtExitFn(); // declaration needed below
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// function template SetLongevity
// Assigns an object a longevity; ensures ordered destructions of objects
// registered thusly during the exit sequence of the application
////////////////////////////////////////////////////////////////////////////////
template <typename T, typename Destroyer>
void SetLongevity(T* pDynObject, unsigned int longevity,
Destroyer d = Private::Deleter<T>::Delete)
{
using namespace Private;
TrackerArray pNewArray = static_cast<TrackerArray>(
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
atexit(Private::AtExitFn);
}
////////////////////////////////////////////////////////////////////////////////
// class template CreateUsingNew
// Implementation of the CreationPolicy used by SingletonHolder
// Creates objects using a straight call to the new operator
////////////////////////////////////////////////////////////////////////////////
struct CreateUsingNew
{
template <class T>
static T* Create(T*)
{ return new T; }
template <class T>
static void Destroy(T* p)
{ delete p; }
};
////////////////////////////////////////////////////////////////////////////////
// class template CreateUsingNew
// Implementation of the CreationPolicy used by SingletonHolder
// Creates objects using a call to std::malloc, followed by a call to the
// placement new operator
////////////////////////////////////////////////////////////////////////////////
struct CreateUsingMalloc
{
template <class T>
static T* Create(T*)
{
void* p = malloc(sizeof(T));
if (!p) return 0;
return new(p) T;
}
template <class T>
static void Destroy(T* p)
{
p->~T();
free(p);
}
};
////////////////////////////////////////////////////////////////////////////////
// class template CreateStatic
// Implementation of the CreationPolicy used by SingletonHolder
// Creates an object in static memory
// Implementation is slightly nonportable because it uses the MaxAlign trick
// (an union of all types to ensure proper memory alignment). This trick is
// nonportable in theory but highly portable in practice.
////////////////////////////////////////////////////////////////////////////////
struct CreateStatic
{
template <class T>
static T* Create(T*)
{
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
static MaxAlign staticMemory_;
return new(&staticMemory_) T;
}
template <class T>
static void Destroy(T* p)
{
p->~T();
}
};
////////////////////////////////////////////////////////////////////////////////
// class template DefaultLifetime
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction as per C++ rules
// Forwards to std::atexit
////////////////////////////////////////////////////////////////////////////////
struct DefaultLifetime
{
template <class T>
static void ScheduleDestruction(T*, void (*pFun)())
{ atexit(pFun); }
template <class T>
static void OnDeadReference(T*)
{ throw std::exception("Dead Reference Detected"); }
};
////////////////////////////////////////////////////////////////////////////////
// class template PhoenixSingleton
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction as per C++ rules, and it allows object
// recreation by not throwing an exception from OnDeadReference
////////////////////////////////////////////////////////////////////////////////
class PhoenixSingleton
{
public:
template <class T>
static void ScheduleDestruction(T*, void (*pFun)())
{
#ifndef ATEXIT_FIXED
if (!destroyedOnce_)
#endif
atexit(pFun);
}
template <class T>
static void OnDeadReference(T*)
{
#ifndef ATEXIT_FIXED
destroyedOnce_ = true;
#endif
}
private:
#ifndef ATEXIT_FIXED
static bool destroyedOnce_;
#endif
};
#ifndef ATEXIT_FIXED
bool PhoenixSingleton::destroyedOnce_ = false;
#endif
////////////////////////////////////////////////////////////////////////////////
// class template Adapter
// Helper for SingletonWithLongevity below
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class T>
struct Adapter
{
void operator()(T*) { pFun_(); }
void (*pFun_)();
};
}
////////////////////////////////////////////////////////////////////////////////
// class template SingletonWithLongevity
// Implementation of the LifetimePolicy used by SingletonHolder
// Schedules an object's destruction in order of their longevities
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
// object
////////////////////////////////////////////////////////////////////////////////
class SingletonWithLongevity
{
public:
template <class T>
static void ScheduleDestruction(T* pObj, void (*pFun)())
{
Private::Adapter<T> adapter = { pFun };
SetLongevity(pObj, GetLongevity(pObj), adapter);
}
template <class T>
static void OnDeadReference(T*)
{ throw std::exception("Dead Reference Detected"); }
};
////////////////////////////////////////////////////////////////////////////////
// class template NoDestroy
// Implementation of the LifetimePolicy used by SingletonHolder
// Never destroys the object
////////////////////////////////////////////////////////////////////////////////
struct NoDestroy
{
template <class T>
static void ScheduleDestruction(T*, void (*)())
{}
template <class T>
static void OnDeadReference(T*)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template SingletonHolder
// Provides Singleton amenities for a type T
// To protect that type from spurious instantiations, you have to protect it
// yourself.
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
class CreationPolicy = CreateUsingNew,
class LifetimePolicy = DefaultLifetime,
class ThreadingModel = SingleThreaded
>
class SingletonHolder
{
public:
static T& Instance();
private:
// Helpers
static void MakeInstance();
static void DestroySingleton();
// Protection
SingletonHolder();
// Data
typedef typename Private::Apply<ThreadingModel,T*>::Result PtrInstanceType;
// typedef typename ThreadingModel::VolatileType<T*>::Result PtrInstanceType;
static PtrInstanceType pInstance_;
static bool destroyed_;
};
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder's data
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class C,
class L,
class M
>
typename SingletonHolder<T, C, L, M>::PtrInstanceType
SingletonHolder<T, C, L, M>::pInstance_;
template
<
class T,
class C,
class L,
class M
>
bool SingletonHolder<T, C, L, M>::destroyed_;
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder::Instance
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class CreationPolicy,
class LifetimePolicy,
class ThreadingModel
>
inline T& SingletonHolder<T, CreationPolicy,
LifetimePolicy, ThreadingModel>::Instance()
{
if (!pInstance_)
{
MakeInstance();
}
return *pInstance_;
}
////////////////////////////////////////////////////////////////////////////////
// SingletonHolder::MakeInstance (helper for Instance)
////////////////////////////////////////////////////////////////////////////////
template
<
class T,
class CreationPolicy,
class LifetimePolicy,
class ThreadingModel
>
void SingletonHolder<T, CreationPolicy,
LifetimePolicy, ThreadingModel>::MakeInstance()
{
typename ThreadingModel::Lock<T> guard;
(void)guard;
if (!pInstance_)
{
if (destroyed_)
{
T* dummy;
LifetimePolicy::OnDeadReference(dummy);
destroyed_ = false;
}
T* dummy;
pInstance_ = CreationPolicy::Create(dummy);
LifetimePolicy::ScheduleDestruction(pInstance_,
&DestroySingleton);
}
}
template
<
class T,
class CreationPolicy,
class L,
class M
>
void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
{
assert(!destroyed_);
CreationPolicy::Destroy(pInstance_);
pInstance_ = 0;
destroyed_ = true;
}
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// January 08, 2002: Fixed bug in call to realloc - credit due to Nigel Gent and
// Eike Petersen
// March 08, 2002: moved the assignment to pTrackerArray in SetLongevity to fix
// exception safety issue. Credit due to Kari Hoijarvi
// May 09, 2002: Fixed bug in Compare that caused longevities to act backwards.
// Credit due to Scott McDonald.
// October 12, 2002: Ported to MSVC 6 by Terje Slettebø.
// Interface for SingletonHolder changed from using template template
// parameters, to using classes with member templates.
////////////////////////////////////////////////////////////////////////////////
#endif // SINGLETON_INC_

View file

@ -1,213 +0,0 @@
#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
////////////////////////////////////////////////////////////////////////////////
class SingleThreaded
{
public:
template <class Host>
struct Lock
{
Lock() {}
Lock(const Host&) {}
};
template <class Host>
struct VolatileType
{
typedef Host Result;
};
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; }
};
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
#include <windows.h>
////////////////////////////////////////////////////////////////////////////////
// class template ObjectLevelLockable
// Implementation of the ThreadingModel policy used by various classes
// Implements a object-level locking scheme
////////////////////////////////////////////////////////////////////////////////
class ObjectLevelLockable
{
CRITICAL_SECTION mtx_;
public:
ObjectLevelLockable()
{
InitializeCriticalSection(&mtx_);
}
~ObjectLevelLockable()
{
DeleteCriticalSection(&mtx_);
}
template <class Host>
class Lock
{
ObjectLevelLockable& host_;
Lock(const Lock&);
Lock& operator=(const Lock&);
public:
Lock(Host& host) : host_(host)
{
::EnterCriticalSection(&host_.mtx_);
}
~Lock()
{
::LeaveCriticalSection(&host_.mtx_);
}
};
template <class Host>
struct VolatileType
{
typedef volatile Host Result;
};
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); }
};
class ClassLevelLockable
{
struct Initializer;
friend struct Initializer;
struct Initializer
{
Initializer()
{
InitializeCriticalSection(&mtx_);
}
~Initializer()
{
DeleteCriticalSection(&mtx_);
}
};
static Initializer initializer_;
public:
static CRITICAL_SECTION mtx_;
template <class Host>
class Lock
{
Lock(const Lock&);
Lock& operator=(const Lock&);
public:
Lock()
{
EnterCriticalSection(&mtx_);
}
Lock(Host&)
{
EnterCriticalSection(&mtx_);
}
~Lock()
{
LeaveCriticalSection(&mtx_);
}
};
template <class Host>
struct VolatileType
{
typedef Host Result;
};
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); }
};
CRITICAL_SECTION ClassLevelLockable::mtx_;
ClassLevelLockable::Initializer ClassLevelLockable::initializer_;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// January 10, 2002: Fixed bug in AtomicDivide - credit due to Jordi Guerrero
// August 14, 2002: Changed some AtomicDivide's to AtomicDecrement's MKH
// October 12, 2002: Ported to MSVC 6 by Terje Slettebø.
// SingleThreaded, ObjectLevelLockable and ClassLevelLockable changed from
// templates to classes with member templates, to be usable as policies in
// the other ported components.
////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -1,106 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: June 20, 2001
#ifndef TYPEINFO_INC_
#define TYPEINFO_INC_
#include <typeinfo>
#include <cassert>
#include "Typelist.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class TypeInfo
// Purpose: offer a first-class, comparable wrapper over std::type_info
////////////////////////////////////////////////////////////////////////////////
class TypeInfo
{
public:
// Constructors
TypeInfo(); // needed for containers
TypeInfo(const std::type_info&); // non-explicit
// Access for the wrapped std::type_info
const std::type_info& Get() const;
// Compatibility functions
bool before(const TypeInfo& rhs) const;
const char* name() const;
private:
const std::type_info* pInfo_;
};
// Implementation
inline TypeInfo::TypeInfo()
{
class Nil {};
pInfo_ = &typeid(Nil);
assert(pInfo_);
}
inline TypeInfo::TypeInfo(const std::type_info& ti)
: pInfo_(&ti)
{ assert(pInfo_); }
inline bool TypeInfo::before(const TypeInfo& rhs) const
{
assert(pInfo_);
return pInfo_->before(*rhs.pInfo_);
}
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(); }
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
{ return lhs.before(rhs); }
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs == rhs); }
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
{ return rhs < lhs; }
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs > rhs); }
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
{ return !(lhs < rhs); }
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEINFO_INC_

View file

@ -1,302 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// 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: August 22, 2001
#ifndef TYPEMANIP_INC_
#define TYPEMANIP_INC_
namespace Loki {
namespace Private {
struct big { char c[2]; };
struct any {
template<typename T>
any(const T&);
};
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// 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;
};
////////////////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////////////////
namespace Private {
namespace Select_ {
struct ChooseT {
template<typename T, typename U>
struct Choose {
typedef T Result;
};
};
struct ChooseU {
template<typename T, typename U>
struct Choose {
typedef U Result;
};
};
template<bool flag>
struct Selector {
typedef ChooseT Result;
};
template<>
struct Selector<false> {
typedef ChooseU Result;
};
} // namespace Select_
} // namespace Private
template<bool flag, typename T, typename U>
struct Select {
private:
typedef typename Private::Select_::Selector<flag>::Result selector;
public:
typedef typename selector::Choose<T, U>::Result Result;
};
namespace Private {
template<typename T>
struct is_void {
enum { value = 0 };
};
template<>
struct is_void<void> {
enum { value = 1 };
};
namespace is_same_ {
template<typename T>
char test_same(T*, T*);
template<typename T>
big test_same(T*, any);
template<typename T, typename U>
struct is_same_imp {
static T t;
static U u;
enum { result = sizeof(test_same(&t, &u)) == sizeof(char) };
};
} // namespace is_same_
template<typename T, typename U>
struct is_same {
enum { voidT = is_void<T>::value };
enum { voidU = is_void<U>::value };
struct BothVoid {
enum { result = 1 };
};
struct OneVoid {
enum { result = 0 };
};
typedef typename Select<voidT & voidU,
BothVoid,
typename Select<voidT | voidU,
OneVoid,
is_same_::is_same_imp<T, U>
>::Result
>::Result tester;
enum { result = tester::result };
};
} // namespace Private
////////////////////////////////////////////////////////////////////////////////
// class template Conversion
// 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.
////////////////////////////////////////////////////////////////////////////////
namespace Private {
namespace Conversion_ {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4181)
#pragma warning(disable:4800)
#pragma warning(disable:4244)
#endif
template<typename T, typename U>
struct Determine {
template<typename X, typename Y>
struct tester {
static char test(X, Y);
static big test(any, any);
};
static T t;
static U u;
enum { exists = sizeof(tester<T, U>::test(t, t)) == sizeof(char) };
enum { exists2Way = exists & (sizeof(tester<U, T>::test(u, u)) == sizeof(char)) };
enum { sameType = exists2Way & is_same<T, U>::result };
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace Conversion_
} // namespace Private
template<typename T, typename U>
struct Conversion {
private:
enum { voidT = Private::is_void<T>::value };
enum { voidU = Private::is_void<U>::value };
struct both_void {
enum { exists = 1, exists2Way = 1, sameType = 1 };
};
struct one_void {
enum { exists = 1, exists2Way = 0, sameType = 0 };
};
typedef typename Select<voidT & voidU,
both_void,
typename Select<voidT | voidU,
one_void,
Private::Conversion_::Determine<T, U>
>::Result
>::Result Chooser;
public:
enum { exists = Chooser::exists };
enum { exists2Way = Chooser::exists2Way };
enum { sameType = Chooser::sameType };
};
////////////////////////////////////////////////////////////////////////////////
// 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!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC
// October 12, 2002: Added SuperSubclass and SuperSubclassStrict templates.
// The corresponding macros are deprecated. T.S.
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEMANIP_INC_

View file

@ -1,374 +0,0 @@
#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 };
};
#ifdef _MSC_VER
template<>
struct IsCustomUnsignedInt<unsigned __int64> {
enum { value = 1 };
};
#endif
////////////////////////////////////////////////////////////////////////////////
// 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 };
};
#ifdef _MSC_VER
template<>
struct IsCustomSignedInt<__int64> {
enum { value = 1 };
};
#endif
////////////////////////////////////////////////////////////////////////////////
// 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;
char test_ptr(const volatile void*, const volatile void*);
big test_ptr(any, any);
template<typename T>
T* unrefptr(T&);
char test_const(const volatile void*);
big test_const(volatile void*);
char test_volatile(const volatile void*);
big test_volatile(const void*);
template<typename V, typename X>
char test_mptr(V X::*, any);
big test_mptr(any, any);
template<bool isReference>
struct AddReferenceImp {
template<typename T>
struct Imp {
typedef T Result;
};
};
template<>
struct AddReferenceImp<false> {
template<typename T>
struct Imp {
typedef T& Result;
};
};
#ifndef _MSC_VER
template <class U> struct PointerTraits
{
enum { result = false };
typedef NullType PointeeType;
};
template <class U> struct PointerTraits<U*>
{
enum { result = true };
typedef U PointeeType;
};
#else
template<typename U>
struct PointerTraits {
private:
static U u;
public:
typedef void PointeeType; // unable to determine correctly
enum { result = sizeof(Private::test_ptr(&u, u)) == sizeof(char) };
};
template<>
struct PointerTraits<void> {
typedef void PointeeType;
enum { result = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct ReferenceTraits
{
enum { result = false };
typedef U ReferredType;
};
template <class U> struct ReferenceTraits<U&>
{
enum { result = true };
typedef U ReferredType;
};
#else
#pragma warning(push)
#pragma warning(disable:4181)
template<typename U>
struct ReferenceTraits {
typedef U const volatile cv_u;
static cv_u u;
public:
enum { result = (sizeof(Private::test_const(&u)) != sizeof(char))
| (sizeof(Private::test_volatile(&u)) != sizeof(char)) };
typedef void ReferredType; // unable to determine correctly
};
#pragma warning(pop)
template<>
struct ReferenceTraits<void> {
enum { result = 0 };
typedef void ReferredType;
};
#endif
#ifndef _MSC_VER
template <class U> struct PToMTraits
{
enum { result = false };
};
template <class U, class V>
struct PToMTraits<U V::*>
{
enum { result = true };
};
#else
template<typename U>
struct PToMTraits {
private:
static U u;
public:
enum { result = sizeof(Private::test_mptr(u, &u)) == sizeof(char) };
};
template<>
struct PToMTraits<void> {
enum { result = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct UnConst
{
typedef U Result;
enum { isConst = 0 };
};
template <class U> struct UnConst<const U>
{
typedef U Result;
enum { isConst = 1 };
};
#else
template<typename U>
struct UnConst {
private:
static U u;
public:
typedef void Result; // unable to determine correctly
enum { isConst = sizeof(Private::test_const(Private::unrefptr(u))) == sizeof(char) };
};
template<>
struct UnConst<void> {
typedef void Result;
enum { isConst = 0 };
};
#endif
#ifndef _MSC_VER
template <class U> struct UnVolatile
{
typedef U Result;
enum { isVolatile = 0 };
};
template <class U> struct UnVolatile<volatile U>
{
typedef U Result;
enum { isVolatile = 1 };
};
#else
template<typename U>
struct UnVolatile {
private:
static U u;
public:
typedef void Result; // unable to determine correctly
enum { isVolatile = sizeof(Private::test_volatile(Private::unrefptr(u))) == sizeof(char) };
};
template<>
struct UnVolatile<void> {
typedef void Result;
enum { isVolatile = 0 };
};
#endif
template<typename U, bool isReference>
struct AddReference {
typedef typename Private::AddReferenceImp<isReference>::template Imp<U>::Result Result;
};
template<>
struct AddReference<void, false> {
typedef void Result;
};
}
////////////////////////////////////////////////////////////////////////////////
// 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
{
public:
enum { isPointer = Private::PointerTraits<T>::result };
typedef typename Private::PointerTraits<T>::PointeeType PointeeType;
enum { isReference = Private::ReferenceTraits<T>::result };
typedef typename Private::ReferenceTraits<T>::ReferredType ReferredType;
enum { isMemberPointer = Private::PToMTraits<T>::result };
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 ||
Conversion<T, void>::sameType };
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 };
typedef typename Select<isStdArith || isPointer || isMemberPointer, T,
typename Private::AddReference<T, isReference>::Result
>::Result ParameterType;
enum { isConst = Private::UnConst<T>::isConst };
typedef typename Private::UnConst<T>::Result NonConstType;
enum { isVolatile = Private::UnVolatile<T>::isVolatile };
typedef typename Private::UnVolatile<T>::Result NonVolatileType;
typedef typename Private::UnVolatile<typename Private::UnConst<T>::Result>::Result
UnqualifiedType;
};
}
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC
////////////////////////////////////////////////////////////////////////////////
#endif // TYPETRAITS_INC_

View file

@ -1,788 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// 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: August 22, 2001
#ifndef TYPELIST_INC_
#define TYPELIST_INC_
#include "NullType.h"
#include "TypeManip.h"
////////////////////////////////////////////////////////////////////////////////
// macros TYPELIST_1, TYPELIST_2, ... TYPELIST_50
// Each takes a number of arguments equal to its numeric suffix
// The arguments are type names. TYPELIST_NN generates a typelist containing
// all types passed as arguments, in that order.
// Example: TYPELIST_2(char, int) generates a type containing char and int.
////////////////////////////////////////////////////////////////////////////////
#define TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType>
#define TYPELIST_2(T1, T2) ::Loki::Typelist<T1, TYPELIST_1(T2) >
#define TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, TYPELIST_2(T2, T3) >
#define TYPELIST_4(T1, T2, T3, T4) \
::Loki::Typelist<T1, TYPELIST_3(T2, T3, T4) >
#define TYPELIST_5(T1, T2, T3, T4, T5) \
::Loki::Typelist<T1, TYPELIST_4(T2, T3, T4, T5) >
#define TYPELIST_6(T1, T2, T3, T4, T5, T6) \
::Loki::Typelist<T1, TYPELIST_5(T2, T3, T4, T5, T6) >
#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \
::Loki::Typelist<T1, TYPELIST_6(T2, T3, T4, T5, T6, T7) >
#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \
::Loki::Typelist<T1, TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) >
#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \
::Loki::Typelist<T1, TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9) >
#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \
::Loki::Typelist<T1, TYPELIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10) >
#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \
::Loki::Typelist<T1, TYPELIST_10(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) >
#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \
::Loki::Typelist<T1, TYPELIST_11(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12) >
#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \
::Loki::Typelist<T1, TYPELIST_12(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13) >
#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14) \
::Loki::Typelist<T1, TYPELIST_13(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14) >
#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15) \
::Loki::Typelist<T1, TYPELIST_14(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15) >
#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16) \
::Loki::Typelist<T1, TYPELIST_15(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16) >
#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17) \
::Loki::Typelist<T1, TYPELIST_16(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17) >
#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18) \
::Loki::Typelist<T1, TYPELIST_17(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18) >
#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19) \
::Loki::Typelist<T1, TYPELIST_18(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19) >
#define TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \
::Loki::Typelist<T1, TYPELIST_19(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) >
#define TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \
::Loki::Typelist<T1, TYPELIST_20(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) >
#define TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \
::Loki::Typelist<T1, TYPELIST_21(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) >
#define TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \
::Loki::Typelist<T1, TYPELIST_22(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) >
#define TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \
::Loki::Typelist<T1, TYPELIST_23(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) >
#define TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \
::Loki::Typelist<T1, TYPELIST_24(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25) >
#define TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26) \
::Loki::Typelist<T1, TYPELIST_25(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26) >
#define TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27) \
::Loki::Typelist<T1, TYPELIST_26(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27) >
#define TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28) \
::Loki::Typelist<T1, TYPELIST_27(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28) >
#define TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29) \
::Loki::Typelist<T1, TYPELIST_28(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29) >
#define TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \
::Loki::Typelist<T1, TYPELIST_29(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) >
#define TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \
::Loki::Typelist<T1, TYPELIST_30(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) >
#define TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \
::Loki::Typelist<T1, TYPELIST_31(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) >
#define TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \
::Loki::Typelist<T1, TYPELIST_32(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) >
#define TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \
::Loki::Typelist<T1, TYPELIST_33(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) >
#define TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35) \
::Loki::Typelist<T1, TYPELIST_34(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35) >
#define TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36) \
::Loki::Typelist<T1, TYPELIST_35(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36) >
#define TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37) \
::Loki::Typelist<T1, TYPELIST_36(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37) >
#define TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38) \
::Loki::Typelist<T1, TYPELIST_37(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38) >
#define TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39) \
::Loki::Typelist<T1, TYPELIST_38(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39) >
#define TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \
::Loki::Typelist<T1, TYPELIST_39(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) >
#define TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \
::Loki::Typelist<T1, TYPELIST_40(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) >
#define TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \
::Loki::Typelist<T1, TYPELIST_41(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) >
#define TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \
::Loki::Typelist<T1, TYPELIST_42(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) >
#define TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \
::Loki::Typelist<T1, TYPELIST_43(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) >
#define TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45) \
::Loki::Typelist<T1, TYPELIST_44(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45) >
#define TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46) \
::Loki::Typelist<T1, TYPELIST_45(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45) >
#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47) \
::Loki::Typelist<T1, TYPELIST_46(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47) >
#define TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48) \
::Loki::Typelist<T1, TYPELIST_47(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48) >
#define TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48, T49) \
::Loki::Typelist<T1, TYPELIST_48(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48, T49) >
#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \
::Loki::Typelist<T1, TYPELIST_49(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) >
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template Typelist
// The building block of typelists of any length
// Use it through the TYPELIST_NN macros
// Defines nested types:
// Head (first element, a non-typelist type by convention)
// Tail (second element, can be another typelist)
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
namespace TL
{
////////////////////////////////////////////////////////////////////////////////
// class template Length
// Computes the length of a typelist
// Invocation (TList is a typelist):
// Length<TList>::value
// returns a compile-time constant containing the length of TList, not counting
// the end terminator (which by convention is NullType)
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct Length;
template <> struct Length<NullType>
{
enum { value = 0 };
};
template <class TList>
struct Length
{
enum { value = 1 + Length<typename TList::Tail>::value };
};
////////////////////////////////////////////////////////////////////////////////
// class template TypeAt
// Finds the type at a given index in a typelist
// Invocation (TList is a typelist and index is a compile-time integral
// constant):
// TypeAt<TList, index>::Result
// returns the type in position 'index' in TList
// If you pass an out-of-bounds index, the result is a compile-time error
////////////////////////////////////////////////////////////////////////////////
namespace TypeAt_ {
template<unsigned int i>
struct Index {
template<class TList>
struct Which {
typedef typename Index<i - 1>::Which<typename TList::Tail>::Result Result;
};
};
template<>
struct Index<0> {
template<class TList>
struct Which {
typedef typename TList::Head Result;
};
};
} // namespace TypeAt_
template<class TList, unsigned int i>
struct TypeAt {
typedef typename TypeAt_::Index<i>::Which<TList>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template TypeAtNonStrict
// Finds the type at a given index in a typelist
// Invocations (TList is a typelist and index is a compile-time integral
// constant):
// a) TypeAt<TList, index>::Result
// returns the type in position 'index' in TList, or NullType if index is
// out-of-bounds
// b) TypeAt<TList, index, D>::Result
// returns the type in position 'index' in TList, or D if index is out-of-bounds
////////////////////////////////////////////////////////////////////////////////
namespace TypeAtNonStrict_ {
template<class TList>
struct ListType;
template<unsigned int index>
struct Index;
template<>
struct ListType<NullType> {
template<unsigned int index, typename DefaultType>
struct Remainder {
typedef DefaultType Result;
};
};
template<>
struct Index<0> {
template<class TList, typename DefaultType>
struct Remainder {
typedef typename TList::Head Result;
};
};
template<unsigned int index>
struct Index {
template<class TList, typename DefaultType>
struct Remainder {
enum { isSameType = Conversion<NullType, typename TList::Tail>::sameType };
typedef typename Select<isSameType, NullType, typename Index<index - 1>::Remainder<typename TList::Tail, DefaultType>::Result>::Result Result;
};
};
template<class TList>
struct ListType {
template<unsigned int index, typename DefaultType>
struct Remainder {
typedef typename Index<index>::Remainder<TList, DefaultType>::Result Result;
};
};
} // namespace TypeAtNonStrict_
template<class TList, unsigned int index, typename DefaultType = NullType>
struct TypeAtNonStrict {
typedef typename TypeAtNonStrict_::ListType<TList>::Remainder<index, DefaultType>::Result Result;
};
} // namespace TL
////////////////////////////////////////////////////////////////////////////////
// class template IndexOf
// Finds the index of a type in a typelist
// Invocation (TList is a typelist and T is a type):
// IndexOf<TList, T>::value
// returns the position of T in TList, or NullType if T is not found in TList
////////////////////////////////////////////////////////////////////////////////
namespace Private {
namespace IndexOf_ {
template<typename TList>
struct Head {
typedef typename TList::Head Result;
};
template<>
struct Head<NullType> {
typedef void Result;
};
struct IsNull {
enum { value = -1 };
};
struct IsTHead {
enum { value = 0 };
};
template<typename TList, typename T>
struct IsNotTHead {
typedef typename TList::Tail Tail;
typedef typename Select<is_same<Tail, NullType>::result,
IsNull,
typename Select<is_same<typename Head<Tail>::Result, T>::result,
IsTHead, IsNotTHead<Tail, T>
>::Result
>::Result chooser;
enum { temp = chooser::value };
enum { value = temp == -1 ? -1 : 1 + temp };
};
template<typename TList, typename T>
struct IsNotNull {
typedef typename Select<is_same<typename TList::Head, T>::result,
IsTHead,
IsNotTHead<TList, T>
>::Result chooser;
enum { value = chooser::value };
};
} // namespace IndexOf_
} // namespace Private
namespace TL {
template<class TList, class T>
struct IndexOf {
private:
typedef typename Select<Private::is_same<TList, NullType>::result,
Private::IndexOf_::IsNull,
Private::IndexOf_::IsNotNull<TList, T>
>::Result chooser;
public:
enum { value = chooser::value };
};
////////////////////////////////////////////////////////////////////////////////
// class template Append
// Appends a type or a typelist to another
// Invocation (TList is a typelist and T is either a type or a typelist):
// Append<TList, T>::Result
// returns a typelist that is TList followed by T and NullType-terminated
////////////////////////////////////////////////////////////////////////////////
namespace Append_ {
template<class T>
struct Helper {
struct big { char i[2]; };
template<class Head, class Tail>
static char Test(const Typelist<Head, Tail>&);
static big Test(...);
static T makeT();
};
} // namespace Append_
template<class TList, class T>
struct Append;
template<>
struct Append<NullType, NullType> {
typedef NullType Result;
};
template<class TList, class T>
struct Append {
private:
enum { T_is_list = sizeof(Append_::Helper<T>::Test(Append_::Helper<T>::MakeT())) == sizeof(char) };
enum { TList_is_null = Conversion<TList, NullType>::sameType };
typedef typename Select<TList_is_null & T_is_list, T, NullType>::Result Result1;
typedef typename Select<TList_is_null & !T_is_list, Typelist<T, NullType>, Result1>::Result Result2;
public:
typedef typename Select<!TList_is_null & !T_is_list, Typelist<typename TList::Head, typename Append<typename TList::Tail, T>::Result>, Result2>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Erase
// Erases the first occurence, if any, of a type in a typelist
// Invocation (TList is a typelist and T is a type):
// Erase<TList, T>::Result
// returns a typelist that is TList without the first occurence of T
////////////////////////////////////////////////////////////////////////////////
template<class TList, class T>
struct Erase {
private:
enum { TList_is_null = Conversion<TList, NullType>::sameType };
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
typedef typename Select<!TList_is_null & Head_is_T, typename TList::Tail, NullType>::Result Result1;
public:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Erase<typename TList::Tail, T>::Result>, Result1>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template EraseAll
// Erases all first occurences, if any, of a type in a typelist
// Invocation (TList is a typelist and T is a type):
// EraseAll<TList, T>::Result
// returns a typelist that is TList without any occurence of T
////////////////////////////////////////////////////////////////////////////////
template<class TList, class T>
struct EraseAll {
private:
enum { TList_is_null = Conversion<TList, NullType>::sameType };
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
typedef typename Select<!TList_is_null & Head_is_T, typename EraseAll<typename TList::Tail, T>::Result, NullType>::Result Result1;
public:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename EraseAll<typename TList::Tail, T>::Result>, Result1>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template NoDuplicates
// Removes all duplicate types in a typelist
// Invocation (TList is a typelist):
// NoDuplicates<TList, T>::Result
////////////////////////////////////////////////////////////////////////////////
template<class TList>
struct NoDuplicates;
template<>
struct NoDuplicates<NullType> {
typedef NullType Result;
};
template<class TList>
struct NoDuplicates {
private:
typedef typename NoDuplicates<typename TList::Tail>::Result L1;
typedef typename Erase<L1, typename TList::Head>::Result L2;
public:
typedef Typelist<typename TList::Head, L2> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Replace
// Replaces the first occurence of a type in a typelist, with another type
// Invocation (TList is a typelist, T, U are types):
// Replace<TList, T, U>::Result
// returns a typelist in which the first occurence of T is replaced with U
////////////////////////////////////////////////////////////////////////////////
template<class TList, class T, class U>
struct Replace {
private:
enum { TList_is_null = Conversion<TList, NullType>::sameType };
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename TList::Tail>, NullType>::Result Result1;
public:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Replace<typename TList::Tail, T, U>::Result>, Result1>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template ReplaceAll
// Replaces all occurences of a type in a typelist, with another type
// Invocation (TList is a typelist, T, U are types):
// Replace<TList, T, U>::Result
// returns a typelist in which all occurences of T is replaced with U
////////////////////////////////////////////////////////////////////////////////
template<class TList, class T, class U>
struct ReplaceAll {
private:
enum { TList_is_null = Conversion<TList, NullType>::sameType };
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename ReplaceAll<typename TList::Tail, T, U>::Result>, NullType>::Result Result1;
public:
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename ReplaceAll<typename TList::Tail, T, U>::Result>, Result1>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Reverse
// Reverses a typelist
// Invocation (TList is a typelist):
// Reverse<TList>::Result
// returns a typelist that is TList reversed
////////////////////////////////////////////////////////////////////////////////
template<class TList>
struct Reverse {
private:
enum { list_of_one = Conversion<typename TList::Tail, NullType>::sameType };
public:
typedef typename Select<list_of_one,
TList,
typename Append<typename Reverse<typename TList::Tail>::Result,
typename TList::Head
>::Result
>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template MostDerived
// Finds the type in a typelist that is the most derived from a given type
// Invocation (TList is a typelist, T is a type):
// Replace<TList, T>::Result
// returns the type in TList that's the most derived from T
////////////////////////////////////////////////////////////////////////////////
template<class TList, class T>
struct MostDerived {
private:
enum { TList_is_null = Conversion<TList, NullType>::sameType };
typedef typename Select<TList_is_null, T, typename MostDerived<typename TList::Tail, T>::Result>::Result Candidate;
public:
typedef typename Select<TList_is_null, T,
typename Select<SUPERSUBCLASS(Candidate, typename TList::Head),
typename TList::Head, Candidate
>::Result
>::Result Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template DerivedToFront
// Arranges the types in a typelist so that the most derived types appear first
// Invocation (TList is a typelist):
// DerivedToFront<TList>::Result
// returns the reordered TList
////////////////////////////////////////////////////////////////////////////////
namespace DerivedToFront_ {
template<class TList>
struct ListType {
};
template<>
struct ListType<NullType> {
typedef NullType Result;
};
} // namespace DerivedToFront_
template<class TList>
struct DerivedToFront;
template<>
struct DerivedToFront<NullType> {
typedef NullType Result;
};
template<class TList>
struct DerivedToFront {
private:
typedef typename MostDerived<typename TList::Tail,
typename TList::Head>::Result TheMostDerived;
typedef typename Replace<typename TList::Tail, TheMostDerived,
typename TList::Head>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result;
};
} // namespace TL
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27
// (credit due to Dave Taylor)
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// August 22, 2001: ported by Jonathan H Lundquist to MSVC
////////////////////////////////////////////////////////////////////////////////
#endif // TYPELIST_INC_