Borland Port from experimental
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@30 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
f9fa5fbbd9
commit
c5ca330861
22 changed files with 7401 additions and 0 deletions
188
Borland/AbstractFactory.h
Normal file
188
Borland/AbstractFactory.h
Normal file
|
@ -0,0 +1,188 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.04; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 ABSTRACTFACTORY_INC_
|
||||
#define ABSTRACTFACTORY_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeManip.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactoryUnit
|
||||
// The building block of an Abstract Factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class AbstractFactoryUnit
|
||||
{
|
||||
public:
|
||||
virtual T* DoCreate(Type2Type<T>) = 0;
|
||||
virtual ~AbstractFactoryUnit() {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactory
|
||||
// Defines an Abstract Factory interface starting from a typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
template <class> class Unit = AbstractFactoryUnit
|
||||
>
|
||||
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
|
||||
{
|
||||
public:
|
||||
typedef TList ProductList;
|
||||
|
||||
template <class T> T* Create()
|
||||
{
|
||||
Unit<T>& unit = *this;
|
||||
return unit.DoCreate(Type2Type<T>());
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template OpNewFactoryUnit
|
||||
// Creates an object by invoking the new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class OpNewFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
return new ConcreteProduct;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PrototypeFactoryUnit
|
||||
// Creates an object by cloning a prototype
|
||||
// There is a difference between the implementation herein and the one described
|
||||
// in the book: GetPrototype and SetPrototype use the helper friend
|
||||
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
|
||||
// name hiding issues. Plus, GetPrototype takes a reference to pointer
|
||||
// instead of returning the pointer by value.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class PrototypeFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
|
||||
PrototypeFactoryUnit(AbstractProduct* p = 0)
|
||||
: pPrototype_(p)
|
||||
{}
|
||||
|
||||
friend void DoGetPrototype(const PrototypeFactoryUnit& me,
|
||||
AbstractProduct*& pPrototype)
|
||||
{ pPrototype = me.pPrototype_; }
|
||||
|
||||
friend void DoSetPrototype(PrototypeFactoryUnit& me,
|
||||
AbstractProduct* pObj)
|
||||
{ me.pPrototype_ = pObj; }
|
||||
|
||||
template <class U>
|
||||
void GetPrototype(AbstractProduct*& p)
|
||||
{ return DoGetPrototype(*this, p); }
|
||||
|
||||
template <class U>
|
||||
void SetPrototype(U* pObj)
|
||||
{ DoSetPrototype(*this, pObj); }
|
||||
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
assert(pPrototype_);
|
||||
return pPrototype_->Clone();
|
||||
}
|
||||
|
||||
private:
|
||||
AbstractProduct* pPrototype_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConcreteFactory
|
||||
// Implements an AbstractFactory interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractFact,
|
||||
template <class, class> class Creator = OpNewFactoryUnit,
|
||||
class TList = typename AbstractFact::ProductList
|
||||
>
|
||||
class ConcreteFactory
|
||||
: public GenLinearHierarchy<
|
||||
typename TL::Reverse<TList>::Result, Creator, AbstractFact>
|
||||
{
|
||||
public:
|
||||
typedef typename AbstractFact::ProductList ProductList;
|
||||
typedef TList ConcreteProductList;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ABSTRACTFACTORY_INC_
|
||||
@
|
611
Borland/AssocVector.h
Normal file
611
Borland/AssocVector.h
Normal file
|
@ -0,0 +1,611 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.04; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
|
||||
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())
|
||||
: std::vector< std::pair<K, V>, A >(alloc), MyCompare(comp)
|
||||
{}
|
||||
|
||||
template <class InputIterator>
|
||||
AssocVector(InputIterator first, InputIterator last,
|
||||
const key_compare& comp = key_compare(),
|
||||
const A& alloc = A())
|
||||
: std::vector< std::pair<K, V>, A >(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 std::vector< std::pair<K, V>, A >::begin(); }
|
||||
const_iterator begin() const { return std::vector< std::pair<K, V>, A >::begin(); }
|
||||
iterator end() { return std::vector< std::pair<K, V>, A >::end(); }
|
||||
const_iterator end() const { return std::vector< std::pair<K, V>, A >::end(); }
|
||||
reverse_iterator rbegin() { return std::vector< std::pair<K, V>, A >::rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return std::vector< std::pair<K, V>, A >::rbegin(); }
|
||||
reverse_iterator rend() { return std::vector< std::pair<K, V>, A >::rend(); }
|
||||
const_reverse_iterator rend() const { return std::vector< std::pair<K, V>, A >::rend(); }
|
||||
|
||||
// capacity:
|
||||
bool empty() const { return std::vector< std::pair<K, V>, A >::empty(); }
|
||||
size_type size() const { return std::vector< std::pair<K, V>, A >::size(); }
|
||||
size_type max_size() { return std::vector< std::pair<K, V>, A >::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 = std::vector< std::pair<K, V>, A >::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 std::vector< std::pair<K, V>, A >::insert(pos, val);
|
||||
}
|
||||
return insert(val).first;
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
iterator insert(InputIterator first, InputIterator last)
|
||||
{ for (; first != last; ++first) insert(*first); }
|
||||
|
||||
void erase(iterator pos)
|
||||
{ std::vector< std::pair<K, V>, A >::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)
|
||||
{ std::vector< std::pair<K, V>, A >::erase(first, last); }
|
||||
|
||||
void swap(AssocVector& other)
|
||||
{
|
||||
using namespace std;
|
||||
std::vector< std::pair<K, V>, A >::swap(other);
|
||||
MyCompare& me = *this;
|
||||
MyCompare& rhs = other;
|
||||
swap(me, rhs);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{ std::vector< std::pair<K, V>, A >::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 std::vector< std::pair<K, V>, A >& me = lhs;
|
||||
return me == rhs;
|
||||
}
|
||||
|
||||
bool operator<(const AssocVector& rhs) const
|
||||
{
|
||||
const std::vector< std::pair<K, V>, A >& me = *this;
|
||||
const std::vector< std::pair<K, V>, A >& 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); }
|
||||
|
||||
#else
|
||||
|
||||
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>
|
||||
iterator 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 namespace std;
|
||||
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); }
|
||||
|
||||
#endif
|
||||
|
||||
} // 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
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ASSOCVECTOR_INC_
|
||||
@
|
61
Borland/EmptyType.h
Normal file
61
Borland/EmptyType.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EMPTYTYPE_INC_
|
||||
@
|
170
Borland/Factory.h
Normal file
170
Borland/Factory.h
Normal file
|
@ -0,0 +1,170 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 FACTORY_INC_
|
||||
#define FACTORY_INC_
|
||||
|
||||
#include "TypeInfo.h"
|
||||
#include "AssocVector.h"
|
||||
#include <exception>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultFactoryError
|
||||
// Manages the "Unknown Type" error in an object factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IdentifierType, class AbstractProduct>
|
||||
struct DefaultFactoryError
|
||||
{
|
||||
struct Exception : public std::exception
|
||||
{
|
||||
#ifdef __BORLANDC__
|
||||
const char* what() { return "Unknown Type"; }
|
||||
#else
|
||||
const char* what() const { return "Unknown Type"; }
|
||||
#endif
|
||||
};
|
||||
|
||||
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::const_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::const_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!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // FACTORY_INC_
|
||||
@
|
1168
Borland/Functor.h
Normal file
1168
Borland/Functor.h
Normal file
File diff suppressed because it is too large
Load diff
286
Borland/HierarchyGenerators.h
Normal file
286
Borland/HierarchyGenerators.h
Normal file
|
@ -0,0 +1,286 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: March 05, 2001
|
||||
|
||||
#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 <class TList, template <class> class Unit>
|
||||
class GenScatterHierarchy;
|
||||
|
||||
template <class T1, class T2, template <class> class Unit>
|
||||
class GenScatterHierarchy<Typelist<T1, T2>, Unit>
|
||||
: public GenScatterHierarchy<T1, Unit>
|
||||
, public GenScatterHierarchy<T2, Unit>
|
||||
{
|
||||
public:
|
||||
typedef Typelist<T1, T2> TList;
|
||||
typedef GenScatterHierarchy<T1, Unit> LeftBase;
|
||||
typedef GenScatterHierarchy<T2, Unit> RightBase;
|
||||
template <typename T> struct Rebind
|
||||
{
|
||||
typedef Unit<T> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <class AtomicType, template <class> class Unit>
|
||||
class GenScatterHierarchy : public Unit<AtomicType>
|
||||
{
|
||||
typedef Unit<AtomicType> LeftBase;
|
||||
template <typename T> struct Rebind
|
||||
{
|
||||
typedef Unit<T> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <template <class> class Unit>
|
||||
class GenScatterHierarchy<NullType, Unit>
|
||||
{
|
||||
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::Rebind<T>::Result& Field(H& obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class T, class H>
|
||||
const typename H::Rebind<T>::Result& Field(const H& 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 <class H, unsigned int i> struct FieldHelper;
|
||||
|
||||
template <class H>
|
||||
struct FieldHelper<H, 0>
|
||||
{
|
||||
typedef typename H::TList::Head ElementType;
|
||||
typedef typename H::Rebind<ElementType>::Result UnitType;
|
||||
|
||||
enum
|
||||
{
|
||||
isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
|
||||
isConst = TypeTraits<H>::isConst
|
||||
};
|
||||
|
||||
typedef const typename H::LeftBase ConstLeftBase;
|
||||
|
||||
typedef typename Select<isConst, ConstLeftBase,
|
||||
typename H::LeftBase>::Result LeftBase;
|
||||
|
||||
typedef typename Select<isTuple, ElementType,
|
||||
UnitType>::Result UnqualifiedResultType;
|
||||
|
||||
typedef typename Select<isConst, const UnqualifiedResultType,
|
||||
UnqualifiedResultType>::Result ResultType;
|
||||
|
||||
static ResultType& Do(H& obj)
|
||||
{
|
||||
LeftBase& leftBase = obj;
|
||||
return leftBase;
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, unsigned int i>
|
||||
struct FieldHelper
|
||||
{
|
||||
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
|
||||
typedef typename H::Rebind<ElementType>::Result UnitType;
|
||||
|
||||
enum
|
||||
{
|
||||
isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
|
||||
isConst = TypeTraits<H>::isConst
|
||||
};
|
||||
|
||||
typedef const typename H::RightBase ConstRightBase;
|
||||
|
||||
typedef typename Select<isConst, ConstRightBase,
|
||||
typename H::RightBase>::Result RightBase;
|
||||
|
||||
typedef typename Select<isTuple, ElementType,
|
||||
UnitType>::Result UnqualifiedResultType;
|
||||
|
||||
typedef typename Select<isConst, const UnqualifiedResultType,
|
||||
UnqualifiedResultType>::Result ResultType;
|
||||
|
||||
static ResultType& Do(H& obj)
|
||||
{
|
||||
RightBase& rightBase = obj;
|
||||
return FieldHelper<RightBase, i - 1>::Do(rightBase);
|
||||
}
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 <int i, class H>
|
||||
typename FieldHelper<H, i>::ResultType&
|
||||
Field(H& obj)
|
||||
{
|
||||
return FieldHelper<H, i>::Do(obj);
|
||||
}
|
||||
|
||||
template <int i, class H>
|
||||
const typename FieldHelper<H, i>::ResultType&
|
||||
Field(const H& obj)
|
||||
{
|
||||
return FieldHelper<H, i>::Do(obj);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenLinearHierarchy
|
||||
// Generates a linear hierarchy starting from a typelist and a template
|
||||
// Invocation (TList is a typelist, Model is a template of two args):
|
||||
// GenScatterHierarchy<TList, Model>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
template <class AtomicType, class Base> class Unit,
|
||||
class Root = EmptyType
|
||||
>
|
||||
class GenLinearHierarchy;
|
||||
|
||||
template
|
||||
<
|
||||
class T1,
|
||||
class T2,
|
||||
template <class, class> class Unit,
|
||||
class Root
|
||||
>
|
||||
class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
|
||||
: public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
|
||||
{
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class, class> class Unit,
|
||||
class Root
|
||||
>
|
||||
class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
|
||||
: public Unit<T, Root>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // HIERARCHYGENERATORS_INC_
|
||||
@
|
447
Borland/MultiMethods.h
Normal file
447
Borland/MultiMethods.h
Normal file
|
@ -0,0 +1,447 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 MULTIMETHODS_INC_
|
||||
#define MULTIMETHODS_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeInfo.h"
|
||||
#include "Functor.h"
|
||||
#include "AssocVector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT NOTE:
|
||||
// The double dispatchers implemented below differ from the excerpts shown in
|
||||
// the book - they are simpler while respecting the same interface.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template InvocationTraits (helper)
|
||||
// Helps implementing optional symmetry
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
class Executor, typename ResultType>
|
||||
struct InvocationTraits
|
||||
{
|
||||
static ResultType
|
||||
DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
|
||||
Executor& exec, Int2Type<false>)
|
||||
{
|
||||
return exec.Fire(lhs, rhs);
|
||||
}
|
||||
static ResultType
|
||||
DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
|
||||
Executor& exec, Int2Type<true>)
|
||||
{
|
||||
return exec.Fire(rhs, lhs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template StaticDispatcher
|
||||
// Implements an automatic static double dispatcher based on two typelists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class Executor,
|
||||
class BaseLhs,
|
||||
class TypesLhs,
|
||||
bool symmetric = true,
|
||||
class BaseRhs = BaseLhs,
|
||||
class TypesRhs = TypesLhs,
|
||||
typename ResultType = void
|
||||
>
|
||||
class StaticDispatcher
|
||||
{
|
||||
template <class SomeLhs>
|
||||
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, NullType)
|
||||
{ return exec.OnError(lhs, rhs); }
|
||||
|
||||
template <class TList, class SomeLhs>
|
||||
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, TList)
|
||||
{
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail 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 TList>
|
||||
static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, TList)
|
||||
{
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail 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!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
@
|
63
Borland/NullType.h
Normal file
63
Borland/NullType.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // NULLTYPE_INC_
|
||||
@
|
73
Borland/Singleton.cpp
Normal file
73
Borland/Singleton.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @// @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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>(std::realloc(
|
||||
pTrackerArray, sizeof(T) * --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
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@
|
474
Borland/Singleton.h
Normal file
474
Borland/Singleton.h
Normal file
|
@ -0,0 +1,474 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class LifetimeTracker
|
||||
// Helper class for SetLongevity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LifetimeTracker
|
||||
{
|
||||
public:
|
||||
LifetimeTracker(unsigned int x) : longevity_(x)
|
||||
{}
|
||||
|
||||
virtual ~LifetimeTracker() = 0;
|
||||
|
||||
static bool Compare(const LifetimeTracker* lhs,
|
||||
const LifetimeTracker* rhs)
|
||||
{
|
||||
return rhs->longevity_ > lhs->longevity_;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int longevity_;
|
||||
};
|
||||
|
||||
// Definition required
|
||||
inline LifetimeTracker::~LifetimeTracker() {}
|
||||
|
||||
// Helper data
|
||||
typedef LifetimeTracker** TrackerArray;
|
||||
extern TrackerArray pTrackerArray;
|
||||
extern unsigned int elements;
|
||||
|
||||
// Helper destroyer function
|
||||
template <typename T>
|
||||
struct Deleter
|
||||
{
|
||||
static void Delete(T* pObj)
|
||||
{ delete pObj; }
|
||||
};
|
||||
|
||||
// Concrete lifetime tracker for objects of type T
|
||||
template <typename T, typename Destroyer>
|
||||
class ConcreteLifetimeTracker : public LifetimeTracker
|
||||
{
|
||||
public:
|
||||
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
|
||||
: LifetimeTracker(longevity)
|
||||
, pTracked_(p)
|
||||
, destroyer_(d)
|
||||
{}
|
||||
|
||||
~ConcreteLifetimeTracker()
|
||||
{ destroyer_(pTracked_); }
|
||||
|
||||
private:
|
||||
T* pTracked_;
|
||||
Destroyer destroyer_;
|
||||
};
|
||||
|
||||
void AtExitFn(); // declaration needed below
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template SetLongevity
|
||||
// Assigns an object a longevity; ensures ordered destructions of objects
|
||||
// registered thusly during the exit sequence of the application
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename Destroyer>
|
||||
void SetLongevity(T* pDynObject, unsigned int longevity,
|
||||
Destroyer d = Private::Deleter<T>::Delete)
|
||||
{
|
||||
using namespace Private;
|
||||
|
||||
TrackerArray pNewArray = static_cast<TrackerArray>(
|
||||
std::realloc(pTrackerArray,
|
||||
sizeof(T) * (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
|
||||
{
|
||||
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 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
|
||||
{
|
||||
//#ifdef __BORLANDC__
|
||||
// static void ScheduleDestruction(T*, void (cdecl *pFun)())
|
||||
//#else
|
||||
static void ScheduleDestruction(T*, void (*pFun)())
|
||||
//#endif
|
||||
{ std::atexit(pFun); }
|
||||
|
||||
static void OnDeadReference()
|
||||
{ throw std::logic_error("Dead Reference Detected"); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PhoenixSingleton
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction as per C++ rules, and it allows object
|
||||
// recreation by not throwing an exception from OnDeadReference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class PhoenixSingleton
|
||||
{
|
||||
public:
|
||||
static void ScheduleDestruction(T*, void (*pFun)())
|
||||
{
|
||||
#ifndef ATEXIT_FIXED
|
||||
if (!destroyedOnce_)
|
||||
#endif
|
||||
std::atexit(pFun);
|
||||
}
|
||||
|
||||
static void OnDeadReference()
|
||||
{
|
||||
#ifndef ATEXIT_FIXED
|
||||
destroyedOnce_ = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifndef ATEXIT_FIXED
|
||||
static bool destroyedOnce_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef ATEXIT_FIXED
|
||||
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Adapter
|
||||
// Helper for SingletonWithLongevity below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class T>
|
||||
struct Adapter
|
||||
{
|
||||
void operator()(T*) { return pFun_(); }
|
||||
void (*pFun_)();
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonWithLongevity
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction in order of their longevities
|
||||
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
|
||||
// object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class SingletonWithLongevity
|
||||
{
|
||||
public:
|
||||
static void ScheduleDestruction(T* pObj, void (*pFun)())
|
||||
{
|
||||
Private::Adapter<T> adapter = { pFun };
|
||||
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
||||
}
|
||||
|
||||
static void OnDeadReference()
|
||||
{ throw std::logic_error("Dead Reference Detected"); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template NoDestroy
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Never destroys the object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct NoDestroy
|
||||
{
|
||||
static void ScheduleDestruction(T*, void (*)())
|
||||
{}
|
||||
|
||||
static void OnDeadReference()
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonHolder
|
||||
// Provides Singleton amenities for a type T
|
||||
// To protect that type from spurious instantiations, you have to protect it
|
||||
// yourself.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
template <class> class CreationPolicy = CreateUsingNew,
|
||||
template <class> class LifetimePolicy = DefaultLifetime,
|
||||
template <class> class ThreadingModel = SingleThreaded
|
||||
>
|
||||
class SingletonHolder
|
||||
{
|
||||
public:
|
||||
static T& Instance();
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
static void MakeInstance();
|
||||
static void DestroySingleton();
|
||||
|
||||
// Protection
|
||||
SingletonHolder();
|
||||
|
||||
// Data
|
||||
typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
|
||||
static PtrInstanceType pInstance_;
|
||||
static bool destroyed_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder's data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class> class C,
|
||||
template <class> class L,
|
||||
template <class> class M
|
||||
>
|
||||
typename SingletonHolder<T, C, L, M>::PtrInstanceType
|
||||
SingletonHolder<T, C, L, M>::pInstance_;
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class> class C,
|
||||
template <class> class L,
|
||||
template <class> class M
|
||||
>
|
||||
bool SingletonHolder<T, C, L, M>::destroyed_;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder::Instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class> class CreationPolicy,
|
||||
template <class> class LifetimePolicy,
|
||||
template <class> class ThreadingModel
|
||||
>
|
||||
inline T& SingletonHolder<T, CreationPolicy,
|
||||
LifetimePolicy, ThreadingModel>::Instance()
|
||||
{
|
||||
if (!pInstance_)
|
||||
{
|
||||
MakeInstance();
|
||||
}
|
||||
return *pInstance_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder::MakeInstance (helper for Instance)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class> class CreationPolicy,
|
||||
template <class> class LifetimePolicy,
|
||||
template <class> class ThreadingModel
|
||||
>
|
||||
void SingletonHolder<T, CreationPolicy,
|
||||
LifetimePolicy, ThreadingModel>::MakeInstance()
|
||||
{
|
||||
typename ThreadingModel<T>::Lock guard;
|
||||
(void)guard;
|
||||
|
||||
if (!pInstance_)
|
||||
{
|
||||
if (destroyed_)
|
||||
{
|
||||
LifetimePolicy<T>::OnDeadReference();
|
||||
destroyed_ = false;
|
||||
}
|
||||
pInstance_ = CreationPolicy<T>::Create();
|
||||
LifetimePolicy<T>::ScheduleDestruction(pInstance_,
|
||||
&DestroySingleton);
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
template <class> class CreationPolicy,
|
||||
template <class> class L,
|
||||
template <class> class M
|
||||
>
|
||||
void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
|
||||
{
|
||||
assert(!destroyed_);
|
||||
CreationPolicy<T>::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
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SINGLETON_INC_
|
||||
@
|
440
Borland/SmallObj.cpp
Normal file
440
Borland/SmallObj.cpp
Normal file
|
@ -0,0 +1,440 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @// @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: March 20, 2001
|
||||
|
||||
#include "SmallObj.h"
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Loki;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Init
|
||||
// Initializes a chunk object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Init(std::size_t blockSize, unsigned char blocks)
|
||||
{
|
||||
assert(blockSize > 0);
|
||||
assert(blocks > 0);
|
||||
// Overflow check
|
||||
assert((blockSize * blocks) / blockSize == blocks);
|
||||
|
||||
pData_ = new unsigned char[blockSize * blocks];
|
||||
Reset(blockSize, blocks);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Reset
|
||||
// Clears an already allocated chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Reset(std::size_t blockSize, unsigned char blocks)
|
||||
{
|
||||
assert(blockSize > 0);
|
||||
assert(blocks > 0);
|
||||
// Overflow check
|
||||
assert((blockSize * blocks) / blockSize == blocks);
|
||||
|
||||
firstAvailableBlock_ = 0;
|
||||
blocksAvailable_ = blocks;
|
||||
|
||||
unsigned char i = 0;
|
||||
unsigned char* p = pData_;
|
||||
for (; i != blocks; p += blockSize)
|
||||
{
|
||||
*p = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Release
|
||||
// Releases the data managed by a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Release()
|
||||
{
|
||||
delete[] pData_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Allocate
|
||||
// Allocates a block from a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* FixedAllocator::Chunk::Allocate(std::size_t blockSize)
|
||||
{
|
||||
if (!blocksAvailable_) return 0;
|
||||
|
||||
assert((firstAvailableBlock_ * blockSize) / blockSize ==
|
||||
firstAvailableBlock_);
|
||||
|
||||
unsigned char* pResult =
|
||||
pData_ + (firstAvailableBlock_ * blockSize);
|
||||
firstAvailableBlock_ = *pResult;
|
||||
--blocksAvailable_;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Deallocate
|
||||
// Dellocates a block from a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Deallocate(void* p, std::size_t blockSize)
|
||||
{
|
||||
assert(p >= pData_);
|
||||
|
||||
unsigned char* toRelease = static_cast<unsigned char*>(p);
|
||||
// Alignment check
|
||||
assert((toRelease - pData_) % blockSize == 0);
|
||||
|
||||
*toRelease = firstAvailableBlock_;
|
||||
firstAvailableBlock_ = static_cast<unsigned char>(
|
||||
(toRelease - pData_) / blockSize);
|
||||
// Truncation check
|
||||
assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);
|
||||
|
||||
++blocksAvailable_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::FixedAllocator
|
||||
// Creates a FixedAllocator object of a fixed block size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::FixedAllocator(std::size_t blockSize)
|
||||
: blockSize_(blockSize)
|
||||
, allocChunk_(0)
|
||||
, deallocChunk_(0)
|
||||
{
|
||||
assert(blockSize_ > 0);
|
||||
|
||||
prev_ = next_ = this;
|
||||
|
||||
std::size_t numBlocks = DEFAULT_CHUNK_SIZE / blockSize;
|
||||
if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX;
|
||||
else if (numBlocks == 0) numBlocks = 8 * blockSize;
|
||||
|
||||
numBlocks_ = static_cast<unsigned char>(numBlocks);
|
||||
assert(numBlocks_ == numBlocks);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::FixedAllocator(const FixedAllocator&)
|
||||
// Creates a FixedAllocator object of a fixed block size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::FixedAllocator(const FixedAllocator& rhs)
|
||||
: blockSize_(rhs.blockSize_)
|
||||
, numBlocks_(rhs.numBlocks_)
|
||||
, chunks_(rhs.chunks_)
|
||||
{
|
||||
prev_ = &rhs;
|
||||
next_ = rhs.next_;
|
||||
rhs.next_->prev_ = this;
|
||||
rhs.next_ = this;
|
||||
|
||||
allocChunk_ = rhs.allocChunk_
|
||||
? &chunks_.front() + (rhs.allocChunk_ - &rhs.chunks_.front())
|
||||
: 0;
|
||||
|
||||
deallocChunk_ = rhs.deallocChunk_
|
||||
? &chunks_.front() + (rhs.deallocChunk_ - &rhs.chunks_.front())
|
||||
: 0;
|
||||
}
|
||||
|
||||
FixedAllocator& FixedAllocator::operator=(const FixedAllocator& rhs)
|
||||
{
|
||||
FixedAllocator copy(rhs);
|
||||
copy.Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::~FixedAllocator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::~FixedAllocator()
|
||||
{
|
||||
if (prev_ != this)
|
||||
{
|
||||
prev_->next_ = next_;
|
||||
next_->prev_ = prev_;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(prev_ == next_);
|
||||
Chunks::iterator i = chunks_.begin();
|
||||
for (; i != chunks_.end(); ++i)
|
||||
{
|
||||
assert(i->blocksAvailable_ == numBlocks_);
|
||||
i->Release();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Swap
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Swap(FixedAllocator& rhs)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
swap(blockSize_, rhs.blockSize_);
|
||||
swap(numBlocks_, rhs.numBlocks_);
|
||||
chunks_.swap(rhs.chunks_);
|
||||
swap(allocChunk_, rhs.allocChunk_);
|
||||
swap(deallocChunk_, rhs.deallocChunk_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Allocate
|
||||
// Allocates a block of fixed size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* FixedAllocator::Allocate()
|
||||
{
|
||||
if (allocChunk_ == 0 || allocChunk_->blocksAvailable_ == 0)
|
||||
{
|
||||
Chunks::iterator i = chunks_.begin();
|
||||
for (;; ++i)
|
||||
{
|
||||
if (i == chunks_.end())
|
||||
{
|
||||
// Initialize
|
||||
chunks_.reserve(chunks_.size() + 1);
|
||||
Chunk newChunk;
|
||||
newChunk.Init(blockSize_, numBlocks_);
|
||||
chunks_.push_back(newChunk);
|
||||
allocChunk_ = &chunks_.back();
|
||||
deallocChunk_ = &chunks_.front();
|
||||
break;
|
||||
}
|
||||
if (i->blocksAvailable_ > 0)
|
||||
{
|
||||
allocChunk_ = &*i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(allocChunk_ != 0);
|
||||
assert(allocChunk_->blocksAvailable_ > 0);
|
||||
|
||||
return allocChunk_->Allocate(blockSize_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Deallocate
|
||||
// Deallocates a block previously allocated with Allocate
|
||||
// (undefined behavior if called with the wrong pointer)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Deallocate(void* p)
|
||||
{
|
||||
assert(!chunks_.empty());
|
||||
assert(&chunks_.front() <= deallocChunk_);
|
||||
assert(&chunks_.back() >= deallocChunk_);
|
||||
|
||||
deallocChunk_ = VicinityFind(p);
|
||||
assert(deallocChunk_);
|
||||
|
||||
DoDeallocate(p);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::VicinityFind (internal)
|
||||
// Finds the chunk corresponding to a pointer, using an efficient search
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p)
|
||||
{
|
||||
assert(!chunks_.empty());
|
||||
assert(deallocChunk_);
|
||||
|
||||
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||
|
||||
Chunk* lo = deallocChunk_;
|
||||
Chunk* hi = deallocChunk_ + 1;
|
||||
Chunk* loBound = &chunks_.front();
|
||||
Chunk* hiBound = &chunks_.back() + 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (lo)
|
||||
{
|
||||
if (p >= lo->pData_ && p < lo->pData_ + chunkLength)
|
||||
{
|
||||
return lo;
|
||||
}
|
||||
if (lo == loBound) lo = 0;
|
||||
else --lo;
|
||||
}
|
||||
|
||||
if (hi)
|
||||
{
|
||||
if (p >= hi->pData_ && p < hi->pData_ + chunkLength)
|
||||
{
|
||||
return hi;
|
||||
}
|
||||
if (++hi == hiBound) hi = 0;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::DoDeallocate (internal)
|
||||
// Performs deallocation. Assumes deallocChunk_ points to the correct chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::DoDeallocate(void* p)
|
||||
{
|
||||
assert(deallocChunk_->pData_ <= p);
|
||||
assert(deallocChunk_->pData_ + numBlocks_ * blockSize_ > p);
|
||||
|
||||
// call into the chunk, will adjust the inner list but won't release memory
|
||||
deallocChunk_->Deallocate(p, blockSize_);
|
||||
|
||||
if (deallocChunk_->blocksAvailable_ == numBlocks_)
|
||||
{
|
||||
// deallocChunk_ is completely free, should we release it?
|
||||
|
||||
Chunk& lastChunk = chunks_.back();
|
||||
|
||||
if (&lastChunk == deallocChunk_)
|
||||
{
|
||||
// check if we have two last chunks empty
|
||||
|
||||
if (chunks_.size() > 1 &&
|
||||
deallocChunk_[-1].blocksAvailable_ == numBlocks_)
|
||||
{
|
||||
// Two free chunks, discard the last one
|
||||
lastChunk.Release();
|
||||
chunks_.pop_back();
|
||||
allocChunk_ = deallocChunk_ = &chunks_.front();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastChunk.blocksAvailable_ == numBlocks_)
|
||||
{
|
||||
// Two free blocks, discard one
|
||||
lastChunk.Release();
|
||||
chunks_.pop_back();
|
||||
allocChunk_ = deallocChunk_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// move the empty chunk to the end
|
||||
std::swap(*deallocChunk_, lastChunk);
|
||||
allocChunk_ = &chunks_.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::SmallObjAllocator
|
||||
// Creates an allocator for small objects given chunk size and maximum 'small'
|
||||
// object size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SmallObjAllocator::SmallObjAllocator(
|
||||
std::size_t chunkSize,
|
||||
std::size_t maxObjectSize)
|
||||
: pLastAlloc_(0), pLastDealloc_(0)
|
||||
, chunkSize_(chunkSize), maxObjectSize_(maxObjectSize)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::Allocate
|
||||
// Allocates 'numBytes' memory
|
||||
// Uses an internal pool of FixedAllocator objects for small objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* SmallObjAllocator::Allocate(std::size_t numBytes)
|
||||
{
|
||||
if (numBytes > maxObjectSize_) return operator new(numBytes);
|
||||
|
||||
if (pLastAlloc_ && pLastAlloc_->BlockSize() == numBytes)
|
||||
{
|
||||
return pLastAlloc_->Allocate();
|
||||
}
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||
if (i == pool_.end() || i->BlockSize() != numBytes)
|
||||
{
|
||||
i = pool_.insert(i, FixedAllocator(numBytes));
|
||||
pLastDealloc_ = &*pool_.begin();
|
||||
}
|
||||
pLastAlloc_ = &*i;
|
||||
return pLastAlloc_->Allocate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::Deallocate
|
||||
// Deallocates memory previously allocated with Allocate
|
||||
// (undefined behavior if you pass any other pointer)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SmallObjAllocator::Deallocate(void* p, std::size_t numBytes)
|
||||
{
|
||||
if (numBytes > maxObjectSize_) return operator delete(p);
|
||||
|
||||
if (pLastDealloc_ && pLastDealloc_->BlockSize() == numBytes)
|
||||
{
|
||||
pLastDealloc_->Deallocate(p);
|
||||
return;
|
||||
}
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||
assert(i != pool_.end());
|
||||
assert(i->BlockSize() == numBytes);
|
||||
pLastDealloc_ = &*i;
|
||||
pLastDealloc_->Deallocate(p);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// March 20: fix exception safety issue in FixedAllocator::Allocate
|
||||
// (thanks to Chris Udazvinis for pointing that out)
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@
|
208
Borland/SmallObj.h
Normal file
208
Borland/SmallObj.h
Normal file
|
@ -0,0 +1,208 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 SMALLOBJ_INC_
|
||||
#define SMALLOBJ_INC_
|
||||
|
||||
#include "Threads.h"
|
||||
#include "Singleton.h"
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#ifndef DEFAULT_CHUNK_SIZE
|
||||
#define DEFAULT_CHUNK_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef MAX_SMALL_OBJECT_SIZE
|
||||
#define MAX_SMALL_OBJECT_SIZE 64
|
||||
#endif
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class FixedAllocator
|
||||
// Offers services for allocating fixed-sized objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FixedAllocator
|
||||
{
|
||||
private:
|
||||
struct Chunk
|
||||
{
|
||||
void Init(std::size_t blockSize, unsigned char blocks);
|
||||
void* Allocate(std::size_t blockSize);
|
||||
void Deallocate(void* p, std::size_t blockSize);
|
||||
void Reset(std::size_t blockSize, unsigned char blocks);
|
||||
void Release();
|
||||
unsigned char* pData_;
|
||||
unsigned char
|
||||
firstAvailableBlock_,
|
||||
blocksAvailable_;
|
||||
};
|
||||
|
||||
// Internal functions
|
||||
void DoDeallocate(void* p);
|
||||
Chunk* VicinityFind(void* p);
|
||||
|
||||
// Data
|
||||
std::size_t blockSize_;
|
||||
unsigned char numBlocks_;
|
||||
typedef std::vector<Chunk> Chunks;
|
||||
Chunks chunks_;
|
||||
Chunk* allocChunk_;
|
||||
Chunk* deallocChunk_;
|
||||
// For ensuring proper copy semantics
|
||||
mutable const FixedAllocator* prev_;
|
||||
mutable const FixedAllocator* next_;
|
||||
|
||||
public:
|
||||
// Create a FixedAllocator able to manage blocks of 'blockSize' size
|
||||
explicit FixedAllocator(std::size_t blockSize = 0);
|
||||
FixedAllocator(const FixedAllocator&);
|
||||
FixedAllocator& operator=(const FixedAllocator&);
|
||||
~FixedAllocator();
|
||||
|
||||
void Swap(FixedAllocator& rhs);
|
||||
|
||||
// Allocate a memory block
|
||||
void* Allocate();
|
||||
// Deallocate a memory block previously allocated with Allocate()
|
||||
// (if that's not the case, the behavior is undefined)
|
||||
void Deallocate(void* p);
|
||||
// Returns the block size with which the FixedAllocator was initialized
|
||||
std::size_t BlockSize() const
|
||||
{ return blockSize_; }
|
||||
// Comparison operator for sorting
|
||||
bool operator<(std::size_t rhs) const
|
||||
{ return BlockSize() < rhs; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SmallObjAllocator
|
||||
// Offers services for allocating small-sized objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SmallObjAllocator
|
||||
{
|
||||
public:
|
||||
SmallObjAllocator(
|
||||
std::size_t chunkSize,
|
||||
std::size_t maxObjectSize);
|
||||
|
||||
void* Allocate(std::size_t numBytes);
|
||||
void Deallocate(void* p, std::size_t size);
|
||||
|
||||
private:
|
||||
SmallObjAllocator(const SmallObjAllocator&);
|
||||
SmallObjAllocator& operator=(const SmallObjAllocator&);
|
||||
|
||||
typedef std::vector<FixedAllocator> Pool;
|
||||
Pool pool_;
|
||||
FixedAllocator* pLastAlloc_;
|
||||
FixedAllocator* pLastDealloc_;
|
||||
std::size_t chunkSize_;
|
||||
std::size_t maxObjectSize_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SmallObject
|
||||
// Base class for polymorphic small objects, offers fast
|
||||
// allocations/deallocations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
template <class> class ThreadingModel = DEFAULT_THREADING,
|
||||
std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
|
||||
std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
|
||||
>
|
||||
class SmallObject : public ThreadingModel<
|
||||
SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
|
||||
{
|
||||
typedef ThreadingModel< SmallObject<ThreadingModel,
|
||||
chunkSize, maxSmallObjectSize> > MyThreadingModel;
|
||||
|
||||
struct MySmallObjAllocator : public SmallObjAllocator
|
||||
{
|
||||
MySmallObjAllocator()
|
||||
: SmallObjAllocator(chunkSize, maxSmallObjectSize)
|
||||
{}
|
||||
};
|
||||
// The typedef below would make things much simpler,
|
||||
// but MWCW won't like it
|
||||
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
|
||||
// DefaultLifetime, ThreadingModel*/> MyAllocator;
|
||||
|
||||
public:
|
||||
static void* operator new(std::size_t size)
|
||||
{
|
||||
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
|
||||
return SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||
PhoenixSingleton>::Instance().Allocate(size);
|
||||
#else
|
||||
return ::operator new(size);
|
||||
#endif
|
||||
}
|
||||
static void operator delete(void* p, std::size_t size)
|
||||
{
|
||||
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
|
||||
SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||
PhoenixSingleton>::Instance().Deallocate(p, size);
|
||||
#else
|
||||
::operator delete(p, size);
|
||||
#endif
|
||||
}
|
||||
virtual ~SmallObject() {}
|
||||
};
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SMALLOBJ_INC_
|
||||
@
|
1219
Borland/SmartPtr.h
Normal file
1219
Borland/SmartPtr.h
Normal file
File diff suppressed because it is too large
Load diff
242
Borland/Threads.h
Normal file
242
Borland/Threads.h
Normal file
|
@ -0,0 +1,242 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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() {}
|
||||
Lock(const Host&) {}
|
||||
};
|
||||
|
||||
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 AtomicDivide(volatile IntType& lval)
|
||||
{ return lval /= val; }
|
||||
|
||||
static void AtomicAssign(volatile IntType & lval, IntType val)
|
||||
{ lval = val; }
|
||||
|
||||
static void AtomicAssign(IntType & lval, volatile IntType & val)
|
||||
{ lval = val; }
|
||||
};
|
||||
|
||||
#ifdef _WINDOWS_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ObjectLevelLockable
|
||||
// Implementation of the ThreadingModel policy used by various classes
|
||||
// Implements a object-level locking scheme
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Host>
|
||||
class ObjectLevelLockable
|
||||
{
|
||||
CRITICAL_SECTION mtx_;
|
||||
|
||||
public:
|
||||
ObjectLevelLockable()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
~ObjectLevelLockable()
|
||||
{
|
||||
::DeleteCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
class Lock;
|
||||
friend class Lock;
|
||||
|
||||
class Lock
|
||||
{
|
||||
ObjectLevelLockable& host_;
|
||||
|
||||
Lock(const Lock&);
|
||||
Lock& operator=(const Lock&);
|
||||
public:
|
||||
Lock(Host& 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 AtomicDivide(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
|
||||
{
|
||||
static CRITICAL_SECTION mtx_;
|
||||
|
||||
struct Initializer;
|
||||
friend struct Initializer;
|
||||
struct Initializer
|
||||
{
|
||||
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(&mtx_);
|
||||
}
|
||||
Lock(Host&)
|
||||
{
|
||||
::EnterCriticalSection(&mtx_);
|
||||
}
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
typedef volatile Host VolatileType;
|
||||
|
||||
typedef LONG IntType;
|
||||
|
||||
static IntType AtomicIncrement(volatile IntType& lval)
|
||||
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static IntType AtomicDivide(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>
|
||||
CRITICAL_SECTION ClassLevelLockable<Host>::mtx_;
|
||||
|
||||
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!!!
|
||||
// January 10, 2002: Fixed bug in AtomicDivide - credit due to Jordi Guerrero
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
@
|
46
Borland/Tuple.h
Normal file
46
Borland/Tuple.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This file is intentionally left empty
|
||||
// Due to compiler limitations, its contents has been moved to
|
||||
// HierarchyGenerators.h
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@
|
130
Borland/TypeInfo.h
Normal file
130
Borland/TypeInfo.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPEINFO_INC_
|
||||
@
|
207
Borland/TypeManip.h
Normal file
207
Borland/TypeManip.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: July 10, 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
|
||||
{
|
||||
static const int 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool flag, typename T, typename U>
|
||||
struct Select
|
||||
{
|
||||
typedef T Result;
|
||||
};
|
||||
template <typename T, typename U>
|
||||
struct Select<false, T, U>
|
||||
{
|
||||
typedef U Result;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class T, class U>
|
||||
struct ConversionHelper
|
||||
{
|
||||
typedef char Small;
|
||||
struct Big { char dummy[2]; };
|
||||
static Big Test(...);
|
||||
static Small Test(U);
|
||||
static T MakeT();
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
{
|
||||
typedef Private::ConversionHelper<T, U> H;
|
||||
|
||||
static const bool exists = sizeof(H::Small) == sizeof((H::Test(H::MakeT())));
|
||||
static const bool exists2Way = exists && Conversion<U, T>::exists;
|
||||
static const bool sameType = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Conversion<T, T>
|
||||
{
|
||||
static const bool exists = true;
|
||||
static const bool exists2Way = true;
|
||||
static const bool sameType = true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Conversion<void, T>
|
||||
{
|
||||
static const bool exists = false;
|
||||
static const bool exists2Way = false;
|
||||
static const bool sameType = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Conversion<T, void>
|
||||
{
|
||||
static const bool exists = true;
|
||||
static const bool exists2Way = false;
|
||||
static const bool sameType = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
class Conversion<void, void>
|
||||
{
|
||||
public:
|
||||
static const bool exists = true;
|
||||
static const bool exists2Way = true;
|
||||
static const bool sameType = true;
|
||||
};
|
||||
|
||||
} // 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS(T, U) \
|
||||
(::Loki::Conversion<const volatile U *, const volatile T *>::exists && \
|
||||
!::Loki::Conversion<const volatile T *, const volatile void *>::sameType)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro SUPERSUBCLASS
|
||||
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
|
||||
// Returns true if B is a public base of D.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS_STRICT(T, U) \
|
||||
((SUPERSUBCLASS(T, U) && \
|
||||
!::Loki::Conversion<const volatile T *, const volatile U *>::sameType))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
// November 22, 2001: fixed bug in Conversion<void, T>
|
||||
// (credit due to Brad Town)
|
||||
// November 23, 2001: (well it's 12:01 am) fixed bug in SUPERSUBCLASS - added
|
||||
// the volatile qualifier to be 100% politically correct
|
||||
// July 16, 2002: Ported by Terje Slettebø to Borland C++ Builder 6.0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPEMANIP_INC_
|
||||
@
|
298
Borland/TypeTraits.h
Normal file
298
Borland/TypeTraits.h
Normal file
|
@ -0,0 +1,298 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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 if 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
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 if 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
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 if 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
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
template <class U> struct PointerTraits
|
||||
{
|
||||
static const bool result = false;
|
||||
typedef NullType PointeeType;
|
||||
};
|
||||
|
||||
template <class U> struct PointerTraits<U *>
|
||||
{
|
||||
static const bool result = true;
|
||||
typedef U PointeeType;
|
||||
};
|
||||
|
||||
template <class U> struct ReferenceTraits
|
||||
{
|
||||
static const bool result = false;
|
||||
typedef U ReferredType;
|
||||
};
|
||||
|
||||
template <class U> struct ReferenceTraits<U &>
|
||||
{
|
||||
static const bool result = true;
|
||||
typedef U ReferredType;
|
||||
};
|
||||
|
||||
template <class U> struct PToMTraits
|
||||
{
|
||||
static const bool result = false;
|
||||
};
|
||||
|
||||
template <class U, class V>
|
||||
struct PToMTraits<U V::*>
|
||||
{
|
||||
static const bool result = true;
|
||||
};
|
||||
|
||||
template <class U> struct UnConst
|
||||
{
|
||||
typedef U Result;
|
||||
static const bool isConst = false;
|
||||
};
|
||||
|
||||
template <class U> struct UnVolatile
|
||||
{
|
||||
typedef U Result;
|
||||
static const bool isVolatile = false;
|
||||
};
|
||||
|
||||
template <class U> struct AddReference
|
||||
{
|
||||
typedef U & Result;
|
||||
};
|
||||
|
||||
template <class U> struct AddReference<U &>
|
||||
{
|
||||
typedef U & Result;
|
||||
};
|
||||
|
||||
template <> struct AddReference<void>
|
||||
{
|
||||
typedef NullType Result;
|
||||
};
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
|
||||
template <class U> struct UnConst<const U>
|
||||
{
|
||||
typedef U Result;
|
||||
static const bool isConst = true;
|
||||
};
|
||||
|
||||
template <class U> struct UnVolatile<volatile U>
|
||||
{
|
||||
typedef U Result;
|
||||
static const bool isVolatile = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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:
|
||||
static const bool isPointer = Private::PointerTraits<T>::result;
|
||||
typedef typename Private::PointerTraits<T>::PointeeType PointeeType;
|
||||
|
||||
static const bool isReference = Private::ReferenceTraits<T>::result;
|
||||
typedef typename Private::ReferenceTraits<T>::ReferredType ReferredType;
|
||||
|
||||
static const bool isMemberPointer = Private::PToMTraits<T>::result;
|
||||
|
||||
static const bool isStdUnsignedInt =
|
||||
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0;
|
||||
|
||||
static const bool isStdSignedInt =
|
||||
TL::IndexOf<Private::StdSignedInts, T>::value >= 0;
|
||||
|
||||
static const bool isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
|
||||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0;
|
||||
static const bool isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0;
|
||||
static const bool isStdArith = isStdIntegral || isStdFloat;
|
||||
static const bool isStdFundamental = isStdArith || isStdFloat ||
|
||||
Conversion<T, void>::sameType;
|
||||
|
||||
static const bool isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value;
|
||||
static const bool isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value;
|
||||
static const bool isIntegral = isStdIntegral || isUnsignedInt || isSignedInt;
|
||||
static const bool isFloat = isStdFloat || IsCustomFloat<T>::value;
|
||||
static const bool isArith = isIntegral || isFloat;
|
||||
static const bool isFundamental = isStdFundamental || isArith || isFloat;
|
||||
|
||||
static const bool temp = isStdArith || isPointer || isMemberPointer;
|
||||
|
||||
typedef typename Select< ::Loki::TypeTraits<T>::temp,
|
||||
T, typename Private::AddReference<T>::Result>::Result ParameterType;
|
||||
|
||||
static const bool isConst = Private::UnConst<T>::isConst;
|
||||
typedef typename Private::UnConst<T>::Result NonConstType;
|
||||
static const bool isVolatile = Private::UnVolatile<T>::isVolatile;
|
||||
typedef typename Private::UnVolatile<T>::Result NonVolatileType;
|
||||
typedef typename Private::UnVolatile<typename Private::UnConst<T>::Result>::Result
|
||||
UnqualifiedType;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPETRAITS_INC_
|
||||
@
|
768
Borland/Typelist.h
Normal file
768
Borland/Typelist.h
Normal file
|
@ -0,0 +1,768 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@///////////////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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 <class T, class U>
|
||||
struct Length< Typelist<T, U> >
|
||||
{
|
||||
static const int value = 1 + Length<U>::value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Length<NullType>
|
||||
{
|
||||
static const int value = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList, int index>
|
||||
struct TypeAt
|
||||
{
|
||||
typedef typename TypeAt<typename TList::Tail, index - 1>::Result Result;
|
||||
};
|
||||
|
||||
template <class Head, class Tail>
|
||||
struct TypeAt<Typelist<Head, Tail>, 0>
|
||||
{
|
||||
typedef Head 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class TList, int index, class DefaultType = NullType>
|
||||
struct TypeAtNonStrict
|
||||
{
|
||||
typedef typename
|
||||
TypeAtNonStrict<typename TList::Tail, index - 1, DefaultType>::Result Result;
|
||||
};
|
||||
|
||||
template<class Head, class Tail, class DefaultType>
|
||||
struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
|
||||
{
|
||||
typedef Head Result;
|
||||
};
|
||||
|
||||
template<int index, class DefaultType>
|
||||
struct TypeAtNonStrict<NullType, index, DefaultType>
|
||||
{
|
||||
typedef DefaultType Result;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class TList, class T>
|
||||
struct IndexOf
|
||||
{
|
||||
private:
|
||||
static const int temp = IndexOf<typename TList::Tail, T>::value;
|
||||
|
||||
public:
|
||||
static const int value = (temp == -1 ? -1 : 1 + temp);
|
||||
};
|
||||
|
||||
template <class T, class Tail>
|
||||
struct IndexOf<Typelist<T, Tail>, T>
|
||||
{
|
||||
static const int value = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct IndexOf<NullType, T>
|
||||
{
|
||||
static const int value = -1;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList, class T>
|
||||
struct Append;
|
||||
|
||||
template <class Head, class Tail, class T>
|
||||
struct Append<Typelist<Head, Tail>, T>
|
||||
{
|
||||
typedef Typelist<Head, typename Append<Tail, T>::Result> Result;
|
||||
};
|
||||
|
||||
template <class Head, class Tail>
|
||||
struct Append<NullType, Typelist<Head, Tail> >
|
||||
{
|
||||
typedef Typelist<Head, Tail> Result;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Append<NullType, T>
|
||||
{
|
||||
typedef TYPELIST_1(T) Result;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Append<NullType, NullType>
|
||||
{
|
||||
typedef NullType 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
|
||||
{
|
||||
typedef Typelist<typename TList::Head,
|
||||
typename Erase<typename TList::Tail, T>::Result> Result;
|
||||
};
|
||||
|
||||
template <class T, class Tail>
|
||||
struct Erase<Typelist<T, Tail>, T>
|
||||
{
|
||||
typedef Tail Result;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Erase<NullType, T>
|
||||
{
|
||||
typedef NullType 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
|
||||
{
|
||||
typedef Typelist<typename TList::Head,
|
||||
typename EraseAll<typename TList::Tail, T>::Result> Result;
|
||||
};
|
||||
|
||||
template <class T, class Tail>
|
||||
struct EraseAll<Typelist<T, Tail>, T>
|
||||
{
|
||||
typedef typename EraseAll<Tail, T>::Result Result;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct EraseAll<NullType, T>
|
||||
{
|
||||
typedef NullType 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 <class Head, class Tail>
|
||||
struct NoDuplicates< Typelist<Head, Tail> >
|
||||
{
|
||||
private:
|
||||
typedef typename NoDuplicates<Tail>::Result L1;
|
||||
typedef typename Erase<L1, Head>::Result L2;
|
||||
|
||||
public:
|
||||
typedef Typelist<Head, L2> Result;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct NoDuplicates<NullType>
|
||||
{
|
||||
typedef NullType 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
|
||||
{
|
||||
typedef Typelist<typename TList::Head,
|
||||
typename Replace<typename TList::Tail, T, U>::Result> Result;
|
||||
};
|
||||
|
||||
template <class T, class Tail, class U>
|
||||
struct Replace<Typelist<T, Tail>, T, U>
|
||||
{
|
||||
typedef Typelist<U, Tail> Result;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct Replace<NullType, T, U>
|
||||
{
|
||||
typedef NullType 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
|
||||
{
|
||||
typedef Typelist<typename TList::Head,
|
||||
typename ReplaceAll<typename TList::Tail, T, U>::Result>
|
||||
Result;
|
||||
};
|
||||
|
||||
template <class T, class Tail, class U>
|
||||
struct ReplaceAll<Typelist<T, Tail>, T, U>
|
||||
{
|
||||
typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct ReplaceAll<NullType, T, U>
|
||||
{
|
||||
typedef NullType 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;
|
||||
|
||||
template <class Head, class Tail>
|
||||
struct Reverse< Typelist<Head, Tail> >
|
||||
{
|
||||
typedef typename Append<
|
||||
typename Reverse<Tail>::Result, Head>::Result Result;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Reverse<NullType>
|
||||
{
|
||||
typedef NullType 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):
|
||||
// MostDerived<TList, T>::Result
|
||||
// returns the type in TList that's the most derived from T
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList, class T>
|
||||
struct MostDerived;
|
||||
|
||||
template <class Head, class Tail, class T>
|
||||
struct MostDerived<Typelist<Head, Tail>, T>
|
||||
{
|
||||
private:
|
||||
typedef typename MostDerived<Tail, T>::Result Candidate;
|
||||
|
||||
public:
|
||||
typedef typename Select<
|
||||
::Loki::Conversion<const volatile Head *, const volatile Candidate *>::exists==1 &&
|
||||
::Loki::Conversion<const volatile Candidate *, const volatile void *>::sameType==0,
|
||||
Head, Candidate>::Result Result;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct MostDerived<NullType, T>
|
||||
{
|
||||
typedef T 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList>
|
||||
struct DerivedToFront;
|
||||
|
||||
template <class Head, class Tail>
|
||||
struct DerivedToFront< Typelist<Head, Tail> >
|
||||
{
|
||||
private:
|
||||
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
|
||||
typedef typename Replace<Tail, TheMostDerived, Head>::Result Temp;
|
||||
typedef typename DerivedToFront<Temp>::Result L;
|
||||
|
||||
public:
|
||||
typedef Typelist<TheMostDerived, L> Result;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DerivedToFront<NullType>
|
||||
{
|
||||
typedef NullType 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!!!
|
||||
// November 22, 2001: fixed bug in DerivedToFront
|
||||
// (credit due to Gianni Luciani who noticed the bug first;
|
||||
// Adam Wilkshire;
|
||||
// Friedrik Hedman who fixed the bug but didn't send the fix;
|
||||
// Kevin Cline who sent the first actual fix)
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPELIST_INC_
|
||||
@
|
226
Borland/Visitor.h
Normal file
226
Borland/Visitor.h
Normal file
|
@ -0,0 +1,226 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 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
|
||||
// The building block of Acyclic Visitor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, typename R = void>
|
||||
class Visitor
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
virtual ReturnType Visit(T&) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Visitor (specialization)
|
||||
// This specialization is not present in the book. It makes it easier to define
|
||||
// Visitors for multiple types in a shot by using a typelist. Example:
|
||||
//
|
||||
// class SomeVisitor :
|
||||
// public BaseVisitor // required
|
||||
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
|
||||
// public Visitor<Paragraph>
|
||||
// {
|
||||
// public:
|
||||
// void Visit(RasterBitmap&); // visit a RasterBitmap
|
||||
// void Visit(Paragraph &); // visit a Paragraph
|
||||
// };
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Head, class Tail, typename R>
|
||||
class Visitor<Typelist<Head, Tail>, R>
|
||||
: public Visitor<Head, R>, public Visitor<Tail, R>
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
// using Visitor<Head, R>::Visit;
|
||||
// using Visitor<Tail, R>::Visit;
|
||||
};
|
||||
|
||||
template <class Head, typename R>
|
||||
class Visitor<Typelist<Head, NullType>, R> : public Visitor<Head, R>
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
using Visitor<Head, R>::Visit;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template BaseVisitorImpl
|
||||
// Implements non-strict visitation (you can implement only part of the Visit
|
||||
// functions)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList, typename R = void> class BaseVisitorImpl;
|
||||
|
||||
template <class Head, class Tail, typename R>
|
||||
class BaseVisitorImpl<Typelist<Head, Tail>, R>
|
||||
: public Visitor<Head, R>
|
||||
, public BaseVisitorImpl<Tail, R>
|
||||
{
|
||||
public:
|
||||
// using BaseVisitorImpl<Tail, R>::Visit;
|
||||
|
||||
virtual R Visit(Head&)
|
||||
{ return R(); }
|
||||
};
|
||||
|
||||
template <class Head, typename R>
|
||||
class BaseVisitorImpl<Typelist<Head, NullType>, R>
|
||||
: public Visitor<Head, R>
|
||||
{
|
||||
public:
|
||||
virtual R Visit(Head&)
|
||||
{ return 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>* p = dynamic_cast<Visitor<T>*>(&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;
|
||||
|
||||
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!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // VISITOR_INC_
|
||||
@
|
1
Borland/portby.txt
Normal file
1
Borland/portby.txt
Normal file
|
@ -0,0 +1 @@
|
|||
?
|
75
Borland/static_check.h
Normal file
75
Borland/static_check.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
head 1.1;
|
||||
access;
|
||||
symbols;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
1.1
|
||||
date 2002.07.16.22.42.05; author tslettebo; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial commit
|
||||
@
|
||||
text
|
||||
@////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef STATIC_CHECK_INC_
|
||||
#define STATIC_CHECK_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper structure for the STATIC_CHECK macro
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int> struct CompileTimeError;
|
||||
template<> struct CompileTimeError<true> {};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro STATIC_CHECK
|
||||
// Invocation: STATIC_CHECK(expr, id)
|
||||
// where:
|
||||
// expr is a compile-time integral or pointer expression
|
||||
// id is a C++ identifier that does not need to be defined
|
||||
// If expr is zero, id will appear in a compile-time error message.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define STATIC_CHECK(expr, msg) \
|
||||
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
|
||||
// definition
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 16, 2002: Ported by Terje Slettebø to BCC 5.6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // STATIC_CHECK_INC_
|
||||
@
|
Loading…
Add table
Add a link
Reference in a new issue