Rani Sharoni's port
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@33 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
b233e001b3
commit
301d96c6a1
26 changed files with 7909 additions and 694 deletions
165
MSVC/1300/AbstractFactory.h
Normal file
165
MSVC/1300/AbstractFactory.h
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef ABSTRACTFACTORY_INC_
|
||||||
|
#define ABSTRACTFACTORY_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "TypeManip.h"
|
||||||
|
#include "HierarchyGenerators.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template AbstractFactoryUnit
|
||||||
|
// The building block of an Abstract Factory
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class AbstractFactoryUnit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual T* DoCreate(Type2Type<T>) = 0;
|
||||||
|
virtual ~AbstractFactoryUnit() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template AbstractFactory
|
||||||
|
// Defines an Abstract Factory interface starting from a typelist
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class TList,
|
||||||
|
template <class> class Unit = AbstractFactoryUnit
|
||||||
|
>
|
||||||
|
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef TList ProductList;
|
||||||
|
|
||||||
|
template <class T> T* Create()
|
||||||
|
{
|
||||||
|
Unit<T>& unit = *this;
|
||||||
|
return unit.DoCreate(Type2Type<T>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template OpNewFactoryUnit
|
||||||
|
// Creates an object by invoking the new operator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class ConcreteProduct, class Base>
|
||||||
|
class OpNewFactoryUnit : public Base
|
||||||
|
{
|
||||||
|
typedef typename Base::ProductList BaseProductList;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef typename BaseProductList::Tail ProductList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename BaseProductList::Head AbstractProduct;
|
||||||
|
ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||||
|
{
|
||||||
|
return new ConcreteProduct;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template PrototypeFactoryUnit
|
||||||
|
// Creates an object by cloning a prototype
|
||||||
|
// There is a difference between the implementation herein and the one described
|
||||||
|
// in the book: GetPrototype and SetPrototype use the helper friend
|
||||||
|
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
|
||||||
|
// name hiding issues. Plus, GetPrototype takes a reference to pointer
|
||||||
|
// instead of returning the pointer by value.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class ConcreteProduct, class Base>
|
||||||
|
class PrototypeFactoryUnit : public Base
|
||||||
|
{
|
||||||
|
typedef typename Base::ProductList BaseProductList;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef typename BaseProductList::Tail ProductList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename BaseProductList::Head AbstractProduct;
|
||||||
|
|
||||||
|
PrototypeFactoryUnit(AbstractProduct* p = 0)
|
||||||
|
: pPrototype_(p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
friend void DoGetPrototype(const PrototypeFactoryUnit& me,
|
||||||
|
AbstractProduct*& pPrototype)
|
||||||
|
{ pPrototype = me.pPrototype_; }
|
||||||
|
|
||||||
|
friend void DoSetPrototype(PrototypeFactoryUnit& me,
|
||||||
|
AbstractProduct* pObj)
|
||||||
|
{ me.pPrototype_ = pObj; }
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
void GetPrototype(AbstractProduct*& p)
|
||||||
|
{ return DoGetPrototype(*this, p); }
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
void SetPrototype(U* pObj)
|
||||||
|
{ DoSetPrototype(*this, pObj); }
|
||||||
|
|
||||||
|
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||||
|
{
|
||||||
|
assert(pPrototype_);
|
||||||
|
return pPrototype_->Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AbstractProduct* pPrototype_;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template ConcreteFactory
|
||||||
|
// Implements an AbstractFactory interface
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class AbstractFact,
|
||||||
|
template <class, class> class Creator = OpNewFactoryUnit,
|
||||||
|
class TList = typename AbstractFact::ProductList
|
||||||
|
>
|
||||||
|
class ConcreteFactory
|
||||||
|
: public GenLinearHierarchy<
|
||||||
|
typename TL::Reverse<TList>::Result, Creator, AbstractFact>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename AbstractFact::ProductList ProductList;
|
||||||
|
typedef TList ConcreteProductList;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // ABSTRACTFACTORY_INC_
|
335
MSVC/1300/AssocVector.h
Normal file
335
MSVC/1300/AssocVector.h
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Wesley Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef ASSOCVECTOR_INC_
|
||||||
|
#define ASSOCVECTOR_INC_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template AssocVectorCompare
|
||||||
|
// Used by AssocVector
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template <class Value, class C>
|
||||||
|
class AssocVectorCompare : public C
|
||||||
|
{
|
||||||
|
typedef std::pair<typename C::first_argument_type, Value>
|
||||||
|
Data;
|
||||||
|
typedef typename C::first_argument_type first_argument_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AssocVectorCompare()
|
||||||
|
{}
|
||||||
|
|
||||||
|
AssocVectorCompare(const C& src) : C(src)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()(const first_argument_type& lhs,
|
||||||
|
const first_argument_type& rhs) const
|
||||||
|
{ return C::operator()(lhs, rhs); }
|
||||||
|
|
||||||
|
bool operator()(const Data& lhs, const Data& rhs) const
|
||||||
|
{ return operator()(lhs.first, rhs.first); }
|
||||||
|
|
||||||
|
bool operator()(const Data& lhs,
|
||||||
|
const first_argument_type& rhs) const
|
||||||
|
{ return operator()(lhs.first, rhs); }
|
||||||
|
|
||||||
|
bool operator()(const first_argument_type& lhs,
|
||||||
|
const Data& rhs) const
|
||||||
|
{ return operator()(lhs, rhs.first); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template AssocVector
|
||||||
|
// An associative vector built as a syntactic drop-in replacement for std::map
|
||||||
|
// BEWARE: AssocVector doesn't respect all map's guarantees, the most important
|
||||||
|
// being:
|
||||||
|
// * iterators are invalidated by insert and erase operations
|
||||||
|
// * the complexity of insert/erase is O(N) not O(log N)
|
||||||
|
// * value_type is std::pair<K, V> not std::pair<const K, V>
|
||||||
|
// * iterators are random
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class K,
|
||||||
|
class V,
|
||||||
|
class C = std::less<K>,
|
||||||
|
class A = std::allocator< std::pair<K, V> >
|
||||||
|
>
|
||||||
|
class AssocVector
|
||||||
|
: private std::vector< std::pair<K, V>, A >
|
||||||
|
, private Private::AssocVectorCompare<V, C>
|
||||||
|
{
|
||||||
|
typedef std::vector<std::pair<K, V>, A> Base;
|
||||||
|
typedef Private::AssocVectorCompare<V, C> MyCompare;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef K key_type;
|
||||||
|
typedef V mapped_type;
|
||||||
|
typedef typename Base::value_type value_type;
|
||||||
|
|
||||||
|
typedef C key_compare;
|
||||||
|
typedef A allocator_type;
|
||||||
|
typedef typename A::reference reference;
|
||||||
|
typedef typename A::const_reference const_reference;
|
||||||
|
typedef typename Base::iterator iterator;
|
||||||
|
typedef typename Base::const_iterator const_iterator;
|
||||||
|
typedef typename Base::size_type size_type;
|
||||||
|
typedef typename Base::difference_type difference_type;
|
||||||
|
typedef typename A::pointer pointer;
|
||||||
|
typedef typename A::const_pointer const_pointer;
|
||||||
|
typedef typename Base::reverse_iterator reverse_iterator;
|
||||||
|
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||||
|
|
||||||
|
class value_compare
|
||||||
|
: public std::binary_function<value_type, value_type, bool>
|
||||||
|
, private key_compare
|
||||||
|
{
|
||||||
|
friend class AssocVector;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
value_compare(key_compare pred) : key_compare(pred)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool operator()(const value_type& lhs, const value_type& rhs) const
|
||||||
|
{ return key_compare::operator()(lhs.first, rhs.first); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 23.3.1.1 construct/copy/destroy
|
||||||
|
|
||||||
|
explicit AssocVector(const key_compare& comp = key_compare(),
|
||||||
|
const A& alloc = A())
|
||||||
|
: Base(alloc), MyCompare(comp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class InputIterator>
|
||||||
|
AssocVector(InputIterator first, InputIterator last,
|
||||||
|
const key_compare& comp = key_compare(),
|
||||||
|
const A& alloc = A())
|
||||||
|
: Base(first, last, alloc), MyCompare(comp)
|
||||||
|
{
|
||||||
|
MyCompare& me = *this;
|
||||||
|
std::sort(begin(), end(), me);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssocVector& operator=(const AssocVector& rhs)
|
||||||
|
{
|
||||||
|
AssocVector(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterators:
|
||||||
|
// The following are here because MWCW gets 'using' wrong
|
||||||
|
iterator begin() { return Base::begin(); }
|
||||||
|
const_iterator begin() const { return Base::begin(); }
|
||||||
|
iterator end() { return Base::end(); }
|
||||||
|
const_iterator end() const { return Base::end(); }
|
||||||
|
reverse_iterator rbegin() { return Base::rbegin(); }
|
||||||
|
const_reverse_iterator rbegin() const { return Base::rbegin(); }
|
||||||
|
reverse_iterator rend() { return Base::rend(); }
|
||||||
|
const_reverse_iterator rend() const { return Base::rend(); }
|
||||||
|
|
||||||
|
// capacity:
|
||||||
|
bool empty() const { return Base::empty(); }
|
||||||
|
size_type size() const { return Base::size(); }
|
||||||
|
size_type max_size() { return Base::max_size(); }
|
||||||
|
|
||||||
|
// 23.3.1.2 element access:
|
||||||
|
mapped_type& operator[](const key_type& key)
|
||||||
|
{ return insert(value_type(key, mapped_type())).first->second; }
|
||||||
|
|
||||||
|
// modifiers:
|
||||||
|
std::pair<iterator, bool> insert(const value_type& val)
|
||||||
|
{
|
||||||
|
bool found(true);
|
||||||
|
iterator i(lower_bound(val.first));
|
||||||
|
|
||||||
|
if (i == end() || this->operator()(val.first, i->first))
|
||||||
|
{
|
||||||
|
i = Base::insert(i, val);
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
return std::make_pair(i, !found);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator insert(iterator pos, const value_type& val)
|
||||||
|
{
|
||||||
|
if (pos != end() && this->operator()(*pos, val) &&
|
||||||
|
(pos == end() - 1 ||
|
||||||
|
!this->operator()(val, pos[1]) &&
|
||||||
|
this->operator()(pos[1], val)))
|
||||||
|
{
|
||||||
|
return Base::insert(pos, val);
|
||||||
|
}
|
||||||
|
return insert(val).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class InputIterator>
|
||||||
|
void insert(InputIterator first, InputIterator last)
|
||||||
|
{ for (; first != last; ++first) insert(*first); }
|
||||||
|
|
||||||
|
void erase(iterator pos)
|
||||||
|
{ Base::erase(pos); }
|
||||||
|
|
||||||
|
size_type erase(const key_type& k)
|
||||||
|
{
|
||||||
|
iterator i(find(k));
|
||||||
|
if (i == end()) return 0;
|
||||||
|
erase(i);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(iterator first, iterator last)
|
||||||
|
{ Base::erase(first, last); }
|
||||||
|
|
||||||
|
void swap(AssocVector& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
Base::swap(other);
|
||||||
|
MyCompare& me = *this;
|
||||||
|
MyCompare& rhs = other;
|
||||||
|
swap(me, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{ Base::clear(); }
|
||||||
|
|
||||||
|
// observers:
|
||||||
|
key_compare key_comp() const
|
||||||
|
{ return *this; }
|
||||||
|
|
||||||
|
value_compare value_comp() const
|
||||||
|
{
|
||||||
|
const key_compare& comp = *this;
|
||||||
|
return value_compare(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 23.3.1.3 map operations:
|
||||||
|
iterator find(const key_type& k)
|
||||||
|
{
|
||||||
|
iterator i(lower_bound(k));
|
||||||
|
if (i != end() && this->operator()(k, i->first))
|
||||||
|
{
|
||||||
|
i = end();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const key_type& k) const
|
||||||
|
{
|
||||||
|
const_iterator i(lower_bound(k));
|
||||||
|
if (i != end() && this->operator()(k, i->first))
|
||||||
|
{
|
||||||
|
i = end();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type count(const key_type& k) const
|
||||||
|
{ return find(k) != end(); }
|
||||||
|
|
||||||
|
iterator lower_bound(const key_type& k)
|
||||||
|
{
|
||||||
|
MyCompare& me = *this;
|
||||||
|
return std::lower_bound(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator lower_bound(const key_type& k) const
|
||||||
|
{
|
||||||
|
const MyCompare& me = *this;
|
||||||
|
return std::lower_bound(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator upper_bound(const key_type& k)
|
||||||
|
{
|
||||||
|
MyCompare& me = *this;
|
||||||
|
return std::upper_bound(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator upper_bound(const key_type& k) const
|
||||||
|
{
|
||||||
|
const MyCompare& me = *this;
|
||||||
|
return std::upper_bound(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> equal_range(const key_type& k)
|
||||||
|
{
|
||||||
|
MyCompare& me = *this;
|
||||||
|
return std::equal_range(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(
|
||||||
|
const key_type& k) const
|
||||||
|
{
|
||||||
|
const MyCompare& me = *this;
|
||||||
|
return std::equal_range(begin(), end(), k, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const AssocVector& lhs, const AssocVector& rhs)
|
||||||
|
{
|
||||||
|
const Base& me = lhs;
|
||||||
|
return me == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const AssocVector& rhs) const
|
||||||
|
{
|
||||||
|
const Base& me = *this;
|
||||||
|
const Base& yo = rhs;
|
||||||
|
return me < yo;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const AssocVector& lhs, const AssocVector& rhs)
|
||||||
|
{ return !(lhs == rhs); }
|
||||||
|
|
||||||
|
friend bool operator>(const AssocVector& lhs, const AssocVector& rhs)
|
||||||
|
{ return rhs < lhs; }
|
||||||
|
|
||||||
|
friend bool operator>=(const AssocVector& lhs, const AssocVector& rhs)
|
||||||
|
{ return !(lhs < rhs); }
|
||||||
|
|
||||||
|
friend bool operator<=(const AssocVector& lhs, const AssocVector& rhs)
|
||||||
|
{ return !(rhs < lhs); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// specialized algorithms:
|
||||||
|
template <class K, class V, class C, class A>
|
||||||
|
void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
|
||||||
|
{ lhs.swap(rhs); }
|
||||||
|
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// May 20, 2001: change operator= - credit due to Cristoph Koegl
|
||||||
|
// June 11, 2001: remove paren in equal_range - credit due to Cristoph Koegl
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// January 22, 2002: fixed operator= - credit due to Tom Hyer
|
||||||
|
// June 25, 2002: fixed template insert() - credit due to Robert Minsk
|
||||||
|
// June 27, 2002: fixed member swap() - credit due to David Brookman
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // ASSOCVECTOR_INC_
|
37
MSVC/1300/EmptyType.h
Normal file
37
MSVC/1300/EmptyType.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: June 20, 2001
|
||||||
|
|
||||||
|
#ifndef EMPTYTYPE_INC_
|
||||||
|
#define EMPTYTYPE_INC_
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class EmptyType
|
||||||
|
// Used as a class type that doesn't hold anything
|
||||||
|
// Useful as a strawman class
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class EmptyType {};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // EMPTYTYPE_INC_
|
143
MSVC/1300/Factory.h
Normal file
143
MSVC/1300/Factory.h
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef FACTORY_INC_
|
||||||
|
#define FACTORY_INC_
|
||||||
|
|
||||||
|
#include "LokiTypeInfo.h"
|
||||||
|
#include "AssocVector.h"
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template DefaultFactoryError
|
||||||
|
// Manages the "Unknown Type" error in an object factory
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename IdentifierType, class AbstractProduct>
|
||||||
|
struct DefaultFactoryError
|
||||||
|
{
|
||||||
|
struct Exception : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const throw() { return "Unknown Type"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static AbstractProduct* OnUnknownType(IdentifierType)
|
||||||
|
{
|
||||||
|
throw Exception();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Factory
|
||||||
|
// Implements a generic object factory
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class AbstractProduct,
|
||||||
|
typename IdentifierType,
|
||||||
|
typename ProductCreator = AbstractProduct* (*)(),
|
||||||
|
template<typename, class>
|
||||||
|
class FactoryErrorPolicy = DefaultFactoryError
|
||||||
|
>
|
||||||
|
class Factory
|
||||||
|
: public FactoryErrorPolicy<IdentifierType, AbstractProduct>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Register(const IdentifierType& id, ProductCreator creator)
|
||||||
|
{
|
||||||
|
return associations_.insert(
|
||||||
|
IdToProductMap::value_type(id, creator)).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Unregister(const IdentifierType& id)
|
||||||
|
{
|
||||||
|
return associations_.erase(id) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProduct* CreateObject(const IdentifierType& id)
|
||||||
|
{
|
||||||
|
typename IdToProductMap::iterator i = associations_.find(id);
|
||||||
|
if (i != associations_.end())
|
||||||
|
{
|
||||||
|
return (i->second)();
|
||||||
|
}
|
||||||
|
return OnUnknownType(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
|
||||||
|
IdToProductMap associations_;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template CloneFactory
|
||||||
|
// Implements a generic cloning factory
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class AbstractProduct,
|
||||||
|
class ProductCreator =
|
||||||
|
AbstractProduct* (*)(const AbstractProduct*),
|
||||||
|
template<typename, class>
|
||||||
|
class FactoryErrorPolicy = DefaultFactoryError
|
||||||
|
>
|
||||||
|
class CloneFactory
|
||||||
|
: public FactoryErrorPolicy<TypeInfo, AbstractProduct>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Register(const TypeInfo& ti, ProductCreator creator)
|
||||||
|
{
|
||||||
|
return associations_.insert(
|
||||||
|
IdToProductMap::value_type(ti, creator)).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Unregister(const TypeInfo& id)
|
||||||
|
{
|
||||||
|
return associations_.erase(id) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProduct* CreateObject(const AbstractProduct* model)
|
||||||
|
{
|
||||||
|
if (model == 0) return 0;
|
||||||
|
|
||||||
|
typename IdToProductMap::iterator i =
|
||||||
|
associations_.find(typeid(*model));
|
||||||
|
if (i != associations_.end())
|
||||||
|
{
|
||||||
|
return (i->second)(model);
|
||||||
|
}
|
||||||
|
return OnUnknownType(typeid(*model));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
|
||||||
|
IdToProductMap associations_;
|
||||||
|
};
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // FACTORY_INC_
|
1347
MSVC/1300/Functor.h
Normal file
1347
MSVC/1300/Functor.h
Normal file
File diff suppressed because it is too large
Load diff
423
MSVC/1300/HierarchyGenerators.h
Normal file
423
MSVC/1300/HierarchyGenerators.h
Normal file
|
@ -0,0 +1,423 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#pragma warning( push )
|
||||||
|
|
||||||
|
// 'class1' : base-class 'class2' is already a base-class of 'class3'
|
||||||
|
#pragma warning( disable : 4584 )
|
||||||
|
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#ifndef HIERARCHYGENERATORS_INC_
|
||||||
|
#define HIERARCHYGENERATORS_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "TypeTraits.h"
|
||||||
|
#include "EmptyType.h"
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template GenScatterHierarchy
|
||||||
|
// Generates a scattered hierarchy starting from a typelist and a template
|
||||||
|
// Invocation (TList is a typelist, Model is a template of one arg):
|
||||||
|
// GenScatterHierarchy<TList, Model>
|
||||||
|
// The generated class inherits all classes generated by instantiating the
|
||||||
|
// template 'Model' with the types contained in TList
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, template <typename> class Unit>
|
||||||
|
class GenScatterHierarchy;
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
// for some reason VC7 needs the base definition altough not in use
|
||||||
|
template <typename TListTag>
|
||||||
|
struct GenScatterHierarchyHelper1
|
||||||
|
{
|
||||||
|
template <typename T, template <typename> class Unit>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TListTag>
|
||||||
|
struct GenScatterHierarchyHelper2
|
||||||
|
{
|
||||||
|
template <typename T, template <typename> class Unit>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper1<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template <class TList, template <typename> class Unit>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef GenScatterHierarchy<typename TList::Head, Unit> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper2<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template <class TList, template <typename> class Unit>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef GenScatterHierarchy<typename TList::Tail, Unit> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper1<TL::NoneList_tag>
|
||||||
|
{
|
||||||
|
template <typename AtomicType, template <typename> class Unit>
|
||||||
|
struct In { typedef Unit<AtomicType> Result; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper2<TL::NoneList_tag>
|
||||||
|
{
|
||||||
|
template <typename AtomicType, template <typename> class Unit>
|
||||||
|
struct In { struct Result {}; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper1<TL::NullType_tag>
|
||||||
|
{
|
||||||
|
template <class TList, template <typename> class Unit>
|
||||||
|
struct In { struct Result {}; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenScatterHierarchyHelper2<TL::NullType_tag>
|
||||||
|
{
|
||||||
|
template <class TList, template <typename> class Unit>
|
||||||
|
struct In { struct Result {}; };
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
template <typename T, template <typename> class Unit>
|
||||||
|
class GenScatterHierarchy
|
||||||
|
: public Private::GenScatterHierarchyHelper1
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, Unit>::Result
|
||||||
|
|
||||||
|
, public Private::GenScatterHierarchyHelper2
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, Unit>::Result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef typename Private::GenScatterHierarchyHelper1
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, Unit>::Result LeftBase;
|
||||||
|
|
||||||
|
typedef typename Private::GenScatterHierarchyHelper2
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, Unit>::Result RightBase;
|
||||||
|
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
TL::is_Typelist<T>::value, T, void
|
||||||
|
>
|
||||||
|
::Result TList;
|
||||||
|
|
||||||
|
template <typename T> struct Rebind
|
||||||
|
{
|
||||||
|
typedef Unit<T> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function template Field
|
||||||
|
// Accesses a field in an object of a type generated with GenScatterHierarchy
|
||||||
|
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
|
||||||
|
// T is a type in the typelist used to generate H):
|
||||||
|
// Field<T>(obj)
|
||||||
|
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T, class H>
|
||||||
|
typename H::template Rebind<T>::Result &
|
||||||
|
Field(H& obj)
|
||||||
|
{
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class H>
|
||||||
|
typename H::template Rebind<T>::Result const &
|
||||||
|
Field(H const & obj)
|
||||||
|
{
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function template TupleUnit
|
||||||
|
// The building block of tuples
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct TupleUnit
|
||||||
|
{
|
||||||
|
T value_;
|
||||||
|
operator T&() { return value_; }
|
||||||
|
operator const T&() const { return value_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Tuple
|
||||||
|
// Implements a tuple class that holds a number of values and provides field
|
||||||
|
// access to them via the Field function (below)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// helper class template FieldHelper
|
||||||
|
// See Field below
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <unsigned int i>
|
||||||
|
struct FieldHelper
|
||||||
|
{
|
||||||
|
template<class H>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
|
||||||
|
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
||||||
|
|
||||||
|
enum { isConst = TypeTraits<H>::isConst };
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isConst,
|
||||||
|
const typename H::RightBase,
|
||||||
|
typename H::RightBase
|
||||||
|
>
|
||||||
|
::Result RightBase;
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
SameType<UnitType, TupleUnit<ElementType> >::value,
|
||||||
|
ElementType,
|
||||||
|
UnitType
|
||||||
|
>
|
||||||
|
::Result UnqualifiedResultType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isConst,
|
||||||
|
const UnqualifiedResultType,
|
||||||
|
UnqualifiedResultType
|
||||||
|
>
|
||||||
|
::Result ResultType;
|
||||||
|
|
||||||
|
static ResultType& Do(H& obj)
|
||||||
|
{
|
||||||
|
RightBase& rightBase = obj;
|
||||||
|
return FieldHelper<i - 1>::template In<RightBase>::Do(rightBase);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct FieldHelper<0>
|
||||||
|
{
|
||||||
|
template<class H>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename H::TList::Head ElementType;
|
||||||
|
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
||||||
|
|
||||||
|
enum { isConst = TypeTraits<H>::isConst };
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isConst,
|
||||||
|
const typename H::LeftBase,
|
||||||
|
typename H::LeftBase
|
||||||
|
>
|
||||||
|
::Result LeftBase;
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
SameType<UnitType, TupleUnit<ElementType> >::value,
|
||||||
|
ElementType,
|
||||||
|
UnitType
|
||||||
|
>
|
||||||
|
::Result UnqualifiedResultType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isConst,
|
||||||
|
const UnqualifiedResultType,
|
||||||
|
UnqualifiedResultType
|
||||||
|
>
|
||||||
|
::Result ResultType;
|
||||||
|
|
||||||
|
static ResultType& Do(H& obj)
|
||||||
|
{
|
||||||
|
LeftBase& leftBase = obj;
|
||||||
|
return leftBase;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function template Field
|
||||||
|
// Accesses a field in an object of a type generated with GenScatterHierarchy
|
||||||
|
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
|
||||||
|
// i is the index of a type in the typelist used to generate H):
|
||||||
|
// Field<i>(obj)
|
||||||
|
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
||||||
|
// and T is the i-th type in the typelist
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <unsigned int i, class H>
|
||||||
|
typename FieldHelper<i>::template In<H>::ResultType&
|
||||||
|
Field(H& obj)
|
||||||
|
{
|
||||||
|
return FieldHelper<i>::template In<H>::Do(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template GenLinearHierarchy
|
||||||
|
// Generates a linear hierarchy starting from a typelist and a template
|
||||||
|
// Invocation (TList is a typelist, Model is a template of two args):
|
||||||
|
// GenLinearHierarchy<TList, Model, Root>
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class TList,
|
||||||
|
template <class AtomicType, class UnitBase> class Unit,
|
||||||
|
class Root = EmptyType
|
||||||
|
>
|
||||||
|
class GenLinearHierarchy;
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename TListTag>
|
||||||
|
struct GenLinearHierarchyHelper
|
||||||
|
{
|
||||||
|
template<class TList, template <class, class> class Unit, class Root>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenLinearHierarchyHelper<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template<class TList, template <class, class> class Unit, class Root>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Unit< Head, GenLinearHierarchy<Tail, Unit, Root> > Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct GenLinearHierarchyHelper<TL::NullType_tag>
|
||||||
|
{
|
||||||
|
template<class TList, template <class, class> class Unit, class Root>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Unit<Head, Root> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class TList,
|
||||||
|
template <class AtomicType, class UnitBase> class Unit,
|
||||||
|
class Root
|
||||||
|
>
|
||||||
|
class GenLinearHierarchy
|
||||||
|
: public Private::GenLinearHierarchyHelper
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
||||||
|
>
|
||||||
|
::template In<TList, Unit, Root>::Result
|
||||||
|
{
|
||||||
|
ASSERT_TYPELIST(TList); // TList must not be NullType
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Private::GenLinearHierarchyHelper
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
||||||
|
>
|
||||||
|
::template In<TList, Unit, Root>::Result LinBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // HIERARCHYGENERATORS_INC_
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning( pop )
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
107
MSVC/1300/LokiTypeInfo.h
Normal file
107
MSVC/1300/LokiTypeInfo.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef TYPEINFO_INC_
|
||||||
|
#define TYPEINFO_INC_
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <cassert>
|
||||||
|
#include "Typelist.h"
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class TypeInfo
|
||||||
|
// Purpose: offer a first-class, comparable wrapper over std::type_info
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TypeInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
TypeInfo(); // needed for containers
|
||||||
|
TypeInfo(const std::type_info&); // non-explicit
|
||||||
|
|
||||||
|
// Access for the wrapped std::type_info
|
||||||
|
const std::type_info& Get() const;
|
||||||
|
// Compatibility functions
|
||||||
|
bool before(const TypeInfo& rhs) const;
|
||||||
|
const char* name() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::type_info* pInfo_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
|
||||||
|
inline TypeInfo::TypeInfo()
|
||||||
|
{
|
||||||
|
class Nil {};
|
||||||
|
pInfo_ = &typeid(Nil);
|
||||||
|
assert(pInfo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TypeInfo::TypeInfo(const std::type_info& ti)
|
||||||
|
: pInfo_(&ti)
|
||||||
|
{ assert(pInfo_); }
|
||||||
|
|
||||||
|
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
||||||
|
{
|
||||||
|
assert(pInfo_);
|
||||||
|
return pInfo_->before(*rhs.pInfo_) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::type_info& TypeInfo::Get() const
|
||||||
|
{
|
||||||
|
assert(pInfo_);
|
||||||
|
return *pInfo_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* TypeInfo::name() const
|
||||||
|
{
|
||||||
|
assert(pInfo_);
|
||||||
|
return pInfo_->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparison operators
|
||||||
|
|
||||||
|
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return (lhs.Get() == rhs.Get()) != 0; }
|
||||||
|
|
||||||
|
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return lhs.before(rhs); }
|
||||||
|
|
||||||
|
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return !(lhs == rhs); }
|
||||||
|
|
||||||
|
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return rhs < lhs; }
|
||||||
|
|
||||||
|
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return !(lhs > rhs); }
|
||||||
|
|
||||||
|
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
|
{ return !(lhs < rhs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // TYPEINFO_INC_
|
112
MSVC/1300/MinMax.h
Normal file
112
MSVC/1300/MinMax.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef MINMAX_INC_
|
||||||
|
#define MINMAX_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "TypeTraits.h"
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
typedef TYPELIST_14(
|
||||||
|
const bool,
|
||||||
|
const char,
|
||||||
|
const signed char,
|
||||||
|
const unsigned char,
|
||||||
|
const wchar_t,
|
||||||
|
const short int,
|
||||||
|
const unsigned short int,
|
||||||
|
const int,
|
||||||
|
const unsigned int,
|
||||||
|
const long int,
|
||||||
|
const unsigned long int,
|
||||||
|
const float,
|
||||||
|
const double,
|
||||||
|
const long double)
|
||||||
|
ArithTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
class MinMaxTraits
|
||||||
|
{
|
||||||
|
typedef typename Loki::Select<Loki::Conversion<R, L>::exists,
|
||||||
|
L, R>::Result
|
||||||
|
T1;
|
||||||
|
|
||||||
|
enum { pos1 = Loki::TL::IndexOf<Private::ArithTypes, const L>::value };
|
||||||
|
enum { pos2 = Loki::TL::IndexOf<Private::ArithTypes, const R>::value };
|
||||||
|
typedef Loki::Select<pos1 != -1 && pos1 < pos2, R, T1>::Result T2;
|
||||||
|
|
||||||
|
enum { rConst = Loki::TypeTraits<R>::isConst >=
|
||||||
|
Loki::TypeTraits<L>::isConst };
|
||||||
|
enum { l2r = rConst && Loki::Conversion<
|
||||||
|
typename Loki::TypeTraits<L>::NonConstType&,
|
||||||
|
typename Loki::TypeTraits<R>::NonConstType&>::exists };
|
||||||
|
typedef typename Loki::Select<l2r, R&, T2>::Result T3;
|
||||||
|
|
||||||
|
enum { lConst = Loki::TypeTraits<L>::isConst >=
|
||||||
|
Loki::TypeTraits<R>::isConst };
|
||||||
|
enum { r2l = lConst && Loki::Conversion<
|
||||||
|
typename Loki::TypeTraits<R>::NonConstType&,
|
||||||
|
typename Loki::TypeTraits<L>::NonConstType&>::exists };
|
||||||
|
public:
|
||||||
|
typedef typename Loki::Select<r2l, L&, T3>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<L, R>::Result
|
||||||
|
Min(L& lhs, R& rhs)
|
||||||
|
{ if (lhs < rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<const L, R>::Result
|
||||||
|
Min(const L& lhs, R& rhs)
|
||||||
|
{ if (lhs < rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<L, const R>::Result
|
||||||
|
Min(L& lhs, const R& rhs)
|
||||||
|
{ if (lhs < rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<const L, const R>::Result
|
||||||
|
Min(const L& lhs, const R& rhs)
|
||||||
|
{ if (lhs < rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<L, R>::Result
|
||||||
|
Max(L& lhs, R& rhs)
|
||||||
|
{ if (lhs > rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<const L, R>::Result
|
||||||
|
Max(const L& lhs, R& rhs)
|
||||||
|
{ if (lhs > rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<L, const R>::Result
|
||||||
|
Max(L& lhs, const R& rhs)
|
||||||
|
{ if (lhs > rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
typename MinMaxTraits<const L, const R>::Result
|
||||||
|
Max(const L& lhs, const R& rhs)
|
||||||
|
{ if (lhs > rhs) return lhs; return rhs; }
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MINMAX_INC_
|
418
MSVC/1300/MultiMethods.h
Normal file
418
MSVC/1300/MultiMethods.h
Normal file
|
@ -0,0 +1,418 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef MULTIMETHODS_INC_
|
||||||
|
#define MULTIMETHODS_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "LokiTypeInfo.h"
|
||||||
|
#include "Functor.h"
|
||||||
|
#include "AssocVector.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IMPORTANT NOTE:
|
||||||
|
// The double dispatchers implemented below differ from the excerpts shown in
|
||||||
|
// the book - they are simpler while respecting the same interface.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template InvocationTraits (helper)
|
||||||
|
// Helps implementing optional symmetry
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template <class SomeLhs, class SomeRhs,
|
||||||
|
class Executor, typename ResultType>
|
||||||
|
struct InvocationTraits
|
||||||
|
{
|
||||||
|
static ResultType
|
||||||
|
DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
|
||||||
|
Executor& exec, Int2Type<false>)
|
||||||
|
{
|
||||||
|
return exec.Fire(lhs, rhs);
|
||||||
|
}
|
||||||
|
static ResultType
|
||||||
|
DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
|
||||||
|
Executor& exec, Int2Type<true>)
|
||||||
|
{
|
||||||
|
return exec.Fire(rhs, lhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template StaticDispatcher
|
||||||
|
// Implements an automatic static double dispatcher based on two typelists
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class Executor,
|
||||||
|
class BaseLhs,
|
||||||
|
class TypesLhs,
|
||||||
|
bool symmetric = true,
|
||||||
|
class BaseRhs = BaseLhs,
|
||||||
|
class TypesRhs = TypesLhs,
|
||||||
|
typename ResultType = void
|
||||||
|
>
|
||||||
|
class StaticDispatcher
|
||||||
|
{
|
||||||
|
template <class SomeLhs>
|
||||||
|
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
|
||||||
|
Executor exec, NullType)
|
||||||
|
{ return exec.OnError(lhs, rhs); }
|
||||||
|
|
||||||
|
template <class Head, class Tail, class SomeLhs>
|
||||||
|
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
|
||||||
|
Executor exec, Typelist<Head, Tail>)
|
||||||
|
{
|
||||||
|
if (Head* p2 = dynamic_cast<Head*>(&rhs))
|
||||||
|
{
|
||||||
|
Int2Type<(symmetric &&
|
||||||
|
int(TL::IndexOf<TypesRhs, Head>::value) <
|
||||||
|
int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t;
|
||||||
|
|
||||||
|
typedef Private::InvocationTraits<
|
||||||
|
SomeLhs, Head, Executor, ResultType> CallTraits;
|
||||||
|
|
||||||
|
return CallTraits::DoDispatch(lhs, *p2, exec, i2t);
|
||||||
|
}
|
||||||
|
return DispatchRhs(lhs, rhs, exec, Tail());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
|
||||||
|
Executor exec, NullType)
|
||||||
|
{ return exec.OnError(lhs, rhs); }
|
||||||
|
|
||||||
|
template <class Head, class Tail>
|
||||||
|
static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
|
||||||
|
Executor exec, Typelist<Head, Tail>)
|
||||||
|
{
|
||||||
|
if (Head* p1 = dynamic_cast<Head*>(&lhs))
|
||||||
|
{
|
||||||
|
return DispatchRhs(*p1, rhs, exec, TypesRhs());
|
||||||
|
}
|
||||||
|
return DispatchLhs(lhs, rhs, exec, Tail());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ResultType Go(BaseLhs& lhs, BaseRhs& rhs,
|
||||||
|
Executor exec)
|
||||||
|
{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template BasicDispatcher
|
||||||
|
// Implements a logarithmic double dispatcher for functors (or functions)
|
||||||
|
// Doesn't offer automated casts or symmetry
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class BaseLhs,
|
||||||
|
class BaseRhs = BaseLhs,
|
||||||
|
typename ResultType = void,
|
||||||
|
typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
|
||||||
|
>
|
||||||
|
class BasicDispatcher
|
||||||
|
{
|
||||||
|
typedef std::pair<TypeInfo,TypeInfo> KeyType;
|
||||||
|
typedef CallbackType MappedType;
|
||||||
|
typedef AssocVector<KeyType, MappedType> MapType;
|
||||||
|
MapType callbackMap_;
|
||||||
|
|
||||||
|
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);
|
||||||
|
bool DoRemove(TypeInfo lhs, TypeInfo rhs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <class SomeLhs, class SomeRhs>
|
||||||
|
void Add(CallbackType fun)
|
||||||
|
{
|
||||||
|
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SomeLhs, class SomeRhs>
|
||||||
|
bool Remove()
|
||||||
|
{
|
||||||
|
return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-inline to reduce compile time overhead...
|
||||||
|
template <class BaseLhs, class BaseRhs,
|
||||||
|
typename ResultType, typename CallbackType>
|
||||||
|
void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
|
||||||
|
::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
|
||||||
|
{
|
||||||
|
callbackMap_[KeyType(lhs, rhs)] = fun;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class BaseLhs, class BaseRhs,
|
||||||
|
typename ResultType, typename CallbackType>
|
||||||
|
bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
|
||||||
|
::DoRemove(TypeInfo lhs, TypeInfo rhs)
|
||||||
|
{
|
||||||
|
return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class BaseLhs, class BaseRhs,
|
||||||
|
typename ResultType, typename CallbackType>
|
||||||
|
ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
|
||||||
|
::Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||||
|
{
|
||||||
|
typename MapType::key_type k(typeid(lhs),typeid(rhs));
|
||||||
|
typename MapType::iterator i = callbackMap_.find(k);
|
||||||
|
if (i == callbackMap_.end())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Function not found");
|
||||||
|
}
|
||||||
|
return (i->second)(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template StaticCaster
|
||||||
|
// Implementation of the CastingPolicy used by FunctorDispatcher
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class To, class From>
|
||||||
|
struct StaticCaster
|
||||||
|
{
|
||||||
|
static To& Cast(From& obj)
|
||||||
|
{
|
||||||
|
return static_cast<To&>(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template DynamicCaster
|
||||||
|
// Implementation of the CastingPolicy used by FunctorDispatcher
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class To, class From>
|
||||||
|
struct DynamicCaster
|
||||||
|
{
|
||||||
|
static To& Cast(From& obj)
|
||||||
|
{
|
||||||
|
return dynamic_cast<To&>(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Private::FnDispatcherHelper
|
||||||
|
// Implements trampolines and argument swapping used by FnDispatcher
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template <class BaseLhs, class BaseRhs,
|
||||||
|
class SomeLhs, class SomeRhs,
|
||||||
|
typename ResultType,
|
||||||
|
class CastLhs, class CastRhs,
|
||||||
|
ResultType (*Callback)(SomeLhs&, SomeRhs&)>
|
||||||
|
struct FnDispatcherHelper
|
||||||
|
{
|
||||||
|
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
|
||||||
|
{
|
||||||
|
return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||||
|
}
|
||||||
|
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
|
||||||
|
{
|
||||||
|
return Trampoline(lhs, rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template FnDispatcher
|
||||||
|
// Implements an automatic logarithmic double dispatcher for functions
|
||||||
|
// Features automated conversions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class BaseLhs, class BaseRhs = BaseLhs,
|
||||||
|
typename ResultType = void,
|
||||||
|
template <class, class> class CastingPolicy = DynamicCaster,
|
||||||
|
template <class, class, class, class>
|
||||||
|
class DispatcherBackend = BasicDispatcher>
|
||||||
|
class FnDispatcher
|
||||||
|
{
|
||||||
|
DispatcherBackend<BaseLhs, BaseRhs, ResultType,
|
||||||
|
ResultType (*)(BaseLhs&, BaseRhs&)> backEnd_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <class SomeLhs, class SomeRhs>
|
||||||
|
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&))
|
||||||
|
{
|
||||||
|
return backEnd_.Add<SomeLhs, SomeRhs>(pFun);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SomeLhs, class SomeRhs,
|
||||||
|
ResultType (*callback)(SomeLhs&, SomeRhs&)>
|
||||||
|
void Add()
|
||||||
|
{
|
||||||
|
typedef Private::FnDispatcherHelper<
|
||||||
|
BaseLhs, BaseRhs,
|
||||||
|
SomeLhs, SomeRhs,
|
||||||
|
ResultType,
|
||||||
|
CastingPolicy<SomeLhs,BaseLhs>,
|
||||||
|
CastingPolicy<SomeRhs,BaseRhs>,
|
||||||
|
callback> Local;
|
||||||
|
|
||||||
|
Add<SomeLhs, SomeRhs>(&Local::Trampoline);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SomeLhs, class SomeRhs,
|
||||||
|
ResultType (*callback)(SomeLhs&, SomeRhs&),
|
||||||
|
bool symmetric>
|
||||||
|
void Add()
|
||||||
|
{
|
||||||
|
typedef Private::FnDispatcherHelper<
|
||||||
|
BaseLhs, BaseRhs,
|
||||||
|
SomeLhs, SomeRhs,
|
||||||
|
ResultType,
|
||||||
|
CastingPolicy<SomeLhs,BaseLhs>,
|
||||||
|
CastingPolicy<SomeRhs,BaseRhs>,
|
||||||
|
callback> Local;
|
||||||
|
|
||||||
|
Add<SomeLhs, SomeRhs>(&Local::Trampoline);
|
||||||
|
if (symmetric)
|
||||||
|
{
|
||||||
|
Add<SomeRhs, SomeLhs>(&Local::TrampolineR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SomeLhs, class SomeRhs>
|
||||||
|
void Remove()
|
||||||
|
{
|
||||||
|
backEnd_.Remove<SomeLhs, SomeRhs>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||||
|
{
|
||||||
|
return backEnd_.Go(lhs, rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template FunctorDispatcherAdaptor
|
||||||
|
// permits use of FunctorDispatcher under gcc.2.95.2/3
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template <class BaseLhs, class BaseRhs,
|
||||||
|
class SomeLhs, class SomeRhs,
|
||||||
|
typename ResultType,
|
||||||
|
class CastLhs, class CastRhs,
|
||||||
|
class Fun, bool SwapArgs>
|
||||||
|
class FunctorDispatcherHelper
|
||||||
|
{
|
||||||
|
Fun fun_;
|
||||||
|
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
|
||||||
|
{
|
||||||
|
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||||
|
}
|
||||||
|
ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
|
||||||
|
{
|
||||||
|
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {}
|
||||||
|
|
||||||
|
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
|
||||||
|
{
|
||||||
|
return Fire(lhs,rhs,Int2Type<SwapArgs>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template FunctorDispatcher
|
||||||
|
// Implements a logarithmic double dispatcher for functors
|
||||||
|
// Features automated casting
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class BaseLhs, class BaseRhs = BaseLhs,
|
||||||
|
typename ResultType = void,
|
||||||
|
template <class, class> class CastingPolicy = DynamicCaster,
|
||||||
|
template <class, class, class, class>
|
||||||
|
class DispatcherBackend = BasicDispatcher>
|
||||||
|
class FunctorDispatcher
|
||||||
|
{
|
||||||
|
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
|
||||||
|
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
|
||||||
|
|
||||||
|
DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <class SomeLhs, class SomeRhs, class Fun>
|
||||||
|
void Add(const Fun& fun)
|
||||||
|
{
|
||||||
|
typedef Private::FunctorDispatcherHelper<
|
||||||
|
BaseLhs, BaseRhs,
|
||||||
|
SomeLhs, SomeRhs,
|
||||||
|
ResultType,
|
||||||
|
CastingPolicy<SomeLhs, BaseLhs>,
|
||||||
|
CastingPolicy<SomeRhs, BaseRhs>,
|
||||||
|
Fun, false> Adapter;
|
||||||
|
|
||||||
|
backEnd_.Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun)));
|
||||||
|
}
|
||||||
|
template <class SomeLhs, class SomeRhs, bool symmetric, class Fun>
|
||||||
|
void Add(const Fun& fun)
|
||||||
|
{
|
||||||
|
Add<SomeLhs,SomeRhs>(fun);
|
||||||
|
|
||||||
|
if (symmetric)
|
||||||
|
{
|
||||||
|
// Note: symmetry only makes sense where BaseLhs==BaseRhs
|
||||||
|
typedef Private::FunctorDispatcherHelper<
|
||||||
|
BaseLhs, BaseLhs,
|
||||||
|
SomeLhs, SomeRhs,
|
||||||
|
ResultType,
|
||||||
|
CastingPolicy<SomeLhs, BaseLhs>,
|
||||||
|
CastingPolicy<SomeRhs, BaseLhs>,
|
||||||
|
Fun, true> AdapterR;
|
||||||
|
|
||||||
|
backEnd_.Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SomeLhs, class SomeRhs>
|
||||||
|
void Remove()
|
||||||
|
{
|
||||||
|
backEnd_.Remove<SomeLhs, SomeRhs>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||||
|
{
|
||||||
|
return backEnd_.Go(lhs, rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,7 +13,7 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: June 20, 2001
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
#ifndef NULLTYPE_INC_
|
#ifndef NULLTYPE_INC_
|
||||||
#define NULLTYPE_INC_
|
#define NULLTYPE_INC_
|
||||||
|
@ -26,12 +26,19 @@ namespace Loki
|
||||||
// Useful as an end marker in typelists
|
// Useful as an end marker in typelists
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class NullType {};
|
class NullType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Head { private: Head(); };
|
||||||
|
struct Tail { private: Tail(); };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // NULLTYPE_INC_
|
#endif // NULLTYPE_INC_
|
||||||
|
|
||||||
|
|
48
MSVC/1300/Singleton.cpp
Normal file
48
MSVC/1300/Singleton.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: June 20, 2001
|
||||||
|
|
||||||
|
#include "Singleton.h"
|
||||||
|
|
||||||
|
using namespace Loki::Private;
|
||||||
|
|
||||||
|
Loki::Private::TrackerArray Loki::Private::pTrackerArray = 0;
|
||||||
|
unsigned int Loki::Private::elements = 0;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function AtExitFn
|
||||||
|
// Ensures proper destruction of objects with longevity
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Loki::Private::AtExitFn()
|
||||||
|
{
|
||||||
|
assert(elements > 0 && pTrackerArray != 0);
|
||||||
|
// Pick the element at the top of the stack
|
||||||
|
LifetimeTracker* pTop = pTrackerArray[elements - 1];
|
||||||
|
// Remove that object off the stack
|
||||||
|
// Don't check errors - realloc with less memory
|
||||||
|
// can't fail
|
||||||
|
pTrackerArray = static_cast<TrackerArray>(std::realloc(
|
||||||
|
pTrackerArray, sizeof(*pTrackerArray) * --elements));
|
||||||
|
// Destroy the element
|
||||||
|
delete pTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
440
MSVC/1300/Singleton.h
Normal file
440
MSVC/1300/Singleton.h
Normal file
|
@ -0,0 +1,440 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef SINGLETON_INC_
|
||||||
|
#define SINGLETON_INC_
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class LifetimeTracker
|
||||||
|
// Helper class for SetLongevity
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class LifetimeTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LifetimeTracker(unsigned int x) : longevity_(x)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual ~LifetimeTracker() = 0;
|
||||||
|
|
||||||
|
static bool Compare(const LifetimeTracker* lhs,
|
||||||
|
const LifetimeTracker* rhs)
|
||||||
|
{
|
||||||
|
return lhs->longevity_ > rhs->longevity_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int longevity_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Definition required
|
||||||
|
inline LifetimeTracker::~LifetimeTracker() {}
|
||||||
|
|
||||||
|
// Helper data
|
||||||
|
typedef LifetimeTracker** TrackerArray;
|
||||||
|
extern TrackerArray pTrackerArray;
|
||||||
|
extern unsigned int elements;
|
||||||
|
|
||||||
|
// Helper destroyer function
|
||||||
|
template <typename T>
|
||||||
|
struct Deleter
|
||||||
|
{
|
||||||
|
static void Delete(T* pObj)
|
||||||
|
{ delete pObj; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Concrete lifetime tracker for objects of type T
|
||||||
|
template <typename T, typename Destroyer>
|
||||||
|
class ConcreteLifetimeTracker : public LifetimeTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
|
||||||
|
: LifetimeTracker(longevity)
|
||||||
|
, pTracked_(p)
|
||||||
|
, destroyer_(d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~ConcreteLifetimeTracker()
|
||||||
|
{ destroyer_(pTracked_); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* pTracked_;
|
||||||
|
Destroyer destroyer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AtExitFn(); // declaration needed below
|
||||||
|
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// function template SetLongevity
|
||||||
|
// Assigns an object a longevity; ensures ordered destructions of objects
|
||||||
|
// registered thusly during the exit sequence of the application
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T, typename Destroyer>
|
||||||
|
void SetLongevity(T* pDynObject, unsigned int longevity,
|
||||||
|
Destroyer d = Private::Deleter<T>::Delete)
|
||||||
|
{
|
||||||
|
using namespace Private;
|
||||||
|
|
||||||
|
TrackerArray pNewArray = static_cast<TrackerArray>(
|
||||||
|
std::realloc(pTrackerArray, sizeof(*pTrackerArray) * (elements + 1)));
|
||||||
|
if (!pNewArray) throw std::bad_alloc();
|
||||||
|
|
||||||
|
// Delayed assignment for exception safety
|
||||||
|
pTrackerArray = pNewArray;
|
||||||
|
|
||||||
|
LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
|
||||||
|
pDynObject, longevity, d);
|
||||||
|
|
||||||
|
// Insert a pointer to the object into the queue
|
||||||
|
TrackerArray pos = std::upper_bound(
|
||||||
|
pTrackerArray,
|
||||||
|
pTrackerArray + elements,
|
||||||
|
p,
|
||||||
|
LifetimeTracker::Compare);
|
||||||
|
std::copy_backward(
|
||||||
|
pos,
|
||||||
|
pTrackerArray + elements,
|
||||||
|
pTrackerArray + elements + 1);
|
||||||
|
*pos = p;
|
||||||
|
++elements;
|
||||||
|
|
||||||
|
// Register a call to AtExitFn
|
||||||
|
std::atexit(Private::AtExitFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template CreateUsingNew
|
||||||
|
// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
|
// Creates objects using a straight call to the new operator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T> struct CreateUsingNew
|
||||||
|
{
|
||||||
|
static T* Create()
|
||||||
|
{ return new T; }
|
||||||
|
|
||||||
|
static void Destroy(T* p)
|
||||||
|
{ delete p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template CreateUsingNew
|
||||||
|
// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
|
// Creates objects using a call to std::malloc, followed by a call to the
|
||||||
|
// placement new operator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T> struct CreateUsingMalloc
|
||||||
|
{
|
||||||
|
static T* Create()
|
||||||
|
{
|
||||||
|
void* p = std::malloc(sizeof(T));
|
||||||
|
if (!p) return 0;
|
||||||
|
return new(p) T;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Destroy(T* p)
|
||||||
|
{
|
||||||
|
p->~T();
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template CreateStatic
|
||||||
|
// Implementation of the CreationPolicy used by SingletonHolder
|
||||||
|
// Creates an object in static memory
|
||||||
|
// Implementation is slightly nonportable because it uses the MaxAlign trick
|
||||||
|
// (an union of all types to ensure proper memory alignment). This trick is
|
||||||
|
// nonportable in theory but highly portable in practice.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T> struct CreateStatic
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning( push )
|
||||||
|
// alignment of a member was sensitive to packing
|
||||||
|
#pragma warning( disable : 4121 )
|
||||||
|
#endif // _MSC_VER
|
||||||
|
union MaxAlign
|
||||||
|
{
|
||||||
|
char t_[sizeof(T)];
|
||||||
|
short int shortInt_;
|
||||||
|
int int_;
|
||||||
|
long int longInt_;
|
||||||
|
float float_;
|
||||||
|
double double_;
|
||||||
|
long double longDouble_;
|
||||||
|
struct Test;
|
||||||
|
int Test::* pMember_;
|
||||||
|
int (Test::*pMemberFn_)(int);
|
||||||
|
};
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning( pop )
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
static T* Create()
|
||||||
|
{
|
||||||
|
static MaxAlign staticMemory_;
|
||||||
|
return new(&staticMemory_) T;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Destroy(T* p)
|
||||||
|
{
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template DefaultLifetime
|
||||||
|
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||||
|
// Schedules an object's destruction as per C++ rules
|
||||||
|
// Forwards to std::atexit
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct DefaultLifetime
|
||||||
|
{
|
||||||
|
static void ScheduleDestruction(T*, void (*pFun)())
|
||||||
|
{ std::atexit(pFun); }
|
||||||
|
|
||||||
|
static void OnDeadReference()
|
||||||
|
{ throw std::logic_error("Dead Reference Detected"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template PhoenixSingleton
|
||||||
|
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||||
|
// Schedules an object's destruction as per C++ rules, and it allows object
|
||||||
|
// recreation by not throwing an exception from OnDeadReference
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class PhoenixSingleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void ScheduleDestruction(T*, void (*pFun)())
|
||||||
|
{
|
||||||
|
#ifndef ATEXIT_FIXED
|
||||||
|
if (!destroyedOnce_)
|
||||||
|
#endif
|
||||||
|
std::atexit(pFun);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnDeadReference()
|
||||||
|
{
|
||||||
|
#ifndef ATEXIT_FIXED
|
||||||
|
destroyedOnce_ = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifndef ATEXIT_FIXED
|
||||||
|
static bool destroyedOnce_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef ATEXIT_FIXED
|
||||||
|
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Adapter
|
||||||
|
// Helper for SingletonWithLongevity below
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct Adapter
|
||||||
|
{
|
||||||
|
void operator()(T*) { return pFun_(); }
|
||||||
|
void (*pFun_)();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template SingletonWithLongevity
|
||||||
|
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||||
|
// Schedules an object's destruction in order of their longevities
|
||||||
|
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
|
||||||
|
// object
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class SingletonWithLongevity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void ScheduleDestruction(T* pObj, void (*pFun)())
|
||||||
|
{
|
||||||
|
Private::Adapter<T> adapter = { pFun };
|
||||||
|
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnDeadReference()
|
||||||
|
{ throw std::logic_error("Dead Reference Detected"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template NoDestroy
|
||||||
|
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||||
|
// Never destroys the object
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct NoDestroy
|
||||||
|
{
|
||||||
|
static void ScheduleDestruction(T*, void (*)())
|
||||||
|
{}
|
||||||
|
|
||||||
|
static void OnDeadReference()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template SingletonHolder
|
||||||
|
// Provides Singleton amenities for a type T
|
||||||
|
// To protect that type from spurious instantiations, you have to protect it
|
||||||
|
// yourself.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class ClientType,
|
||||||
|
class ThreadingModelType,
|
||||||
|
class PtrInstanceType
|
||||||
|
>
|
||||||
|
class SingletonHolderStaticData
|
||||||
|
{
|
||||||
|
friend ClientType; // illegal (11.4/2) but works with VC
|
||||||
|
static ThreadingModelType s_ThreadingModelData;
|
||||||
|
static PtrInstanceType s_pInstance;
|
||||||
|
static bool s_destroyed;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class C, class M, class P>
|
||||||
|
M SingletonHolderStaticData<C, M, P>::s_ThreadingModelData;
|
||||||
|
|
||||||
|
template<class C, class M, class P>
|
||||||
|
P SingletonHolderStaticData<C, M, P>::s_pInstance;
|
||||||
|
|
||||||
|
template<class C, class M, class P>
|
||||||
|
bool SingletonHolderStaticData<C, M, P>::s_destroyed;
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename T,
|
||||||
|
template <class> class CreationPolicy = CreateUsingNew,
|
||||||
|
template <class> class LifetimePolicy = DefaultLifetime,
|
||||||
|
template <class> class ThreadingModel = SingleThreaded
|
||||||
|
>
|
||||||
|
class SingletonHolder
|
||||||
|
{
|
||||||
|
typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
|
||||||
|
|
||||||
|
typedef SingletonHolderStaticData
|
||||||
|
<
|
||||||
|
SingletonHolder,
|
||||||
|
ThreadingModel<T>,
|
||||||
|
PtrInstanceType
|
||||||
|
>
|
||||||
|
MySingletonHolderStaticData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static T& Instance()
|
||||||
|
{
|
||||||
|
if (!pInstance_())
|
||||||
|
{
|
||||||
|
MakeInstance();
|
||||||
|
}
|
||||||
|
return *pInstance_();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helpers
|
||||||
|
static void MakeInstance()
|
||||||
|
{
|
||||||
|
typename ThreadingModel<T>::Lock guard(
|
||||||
|
MySingletonHolderStaticData::s_ThreadingModelData);
|
||||||
|
|
||||||
|
(void)guard;
|
||||||
|
|
||||||
|
if (!pInstance_())
|
||||||
|
{
|
||||||
|
if (destroyed_())
|
||||||
|
{
|
||||||
|
LifetimePolicy<T>::OnDeadReference();
|
||||||
|
destroyed_() = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInstance_() = CreationPolicy<T>::Create();
|
||||||
|
|
||||||
|
LifetimePolicy<T>::ScheduleDestruction
|
||||||
|
(
|
||||||
|
pInstance_(),
|
||||||
|
&DestroySingleton
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroySingleton()
|
||||||
|
{
|
||||||
|
assert(!destroyed_());
|
||||||
|
CreationPolicy<T>::Destroy(pInstance_());
|
||||||
|
pInstance_() = 0;
|
||||||
|
destroyed_() = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protection
|
||||||
|
SingletonHolder();
|
||||||
|
|
||||||
|
// Data
|
||||||
|
static PtrInstanceType &pInstance_()
|
||||||
|
{
|
||||||
|
return MySingletonHolderStaticData::s_pInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool &destroyed_()
|
||||||
|
{
|
||||||
|
return MySingletonHolderStaticData::s_destroyed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // SINGLETON_INC_
|
418
MSVC/1300/SmallObj.cpp
Normal file
418
MSVC/1300/SmallObj.cpp
Normal file
|
@ -0,0 +1,418 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: March 20, 2001
|
||||||
|
|
||||||
|
#include "SmallObj.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace Loki;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Chunk::Init
|
||||||
|
// Initializes a chunk object
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Chunk::Init(std::size_t blockSize, unsigned char blocks)
|
||||||
|
{
|
||||||
|
assert(blockSize > 0);
|
||||||
|
assert(blocks > 0);
|
||||||
|
// Overflow check
|
||||||
|
assert((blockSize * blocks) / blockSize == blocks);
|
||||||
|
|
||||||
|
pData_ = new unsigned char[blockSize * blocks];
|
||||||
|
Reset(blockSize, blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Chunk::Reset
|
||||||
|
// Clears an already allocated chunk
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Chunk::Reset(std::size_t blockSize, unsigned char blocks)
|
||||||
|
{
|
||||||
|
assert(blockSize > 0);
|
||||||
|
assert(blocks > 0);
|
||||||
|
// Overflow check
|
||||||
|
assert((blockSize * blocks) / blockSize == blocks);
|
||||||
|
|
||||||
|
firstAvailableBlock_ = 0;
|
||||||
|
blocksAvailable_ = blocks;
|
||||||
|
|
||||||
|
unsigned char i = 0;
|
||||||
|
unsigned char* p = pData_;
|
||||||
|
for (; i != blocks; p += blockSize)
|
||||||
|
{
|
||||||
|
*p = ++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Chunk::Release
|
||||||
|
// Releases the data managed by a chunk
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Chunk::Release()
|
||||||
|
{
|
||||||
|
delete[] pData_;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Chunk::Allocate
|
||||||
|
// Allocates a block from a chunk
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* FixedAllocator::Chunk::Allocate(std::size_t blockSize)
|
||||||
|
{
|
||||||
|
if (!blocksAvailable_) return 0;
|
||||||
|
|
||||||
|
assert((firstAvailableBlock_ * blockSize) / blockSize ==
|
||||||
|
firstAvailableBlock_);
|
||||||
|
|
||||||
|
unsigned char* pResult =
|
||||||
|
pData_ + (firstAvailableBlock_ * blockSize);
|
||||||
|
firstAvailableBlock_ = *pResult;
|
||||||
|
--blocksAvailable_;
|
||||||
|
|
||||||
|
return pResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Chunk::Deallocate
|
||||||
|
// Dellocates a block from a chunk
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Chunk::Deallocate(void* p, std::size_t blockSize)
|
||||||
|
{
|
||||||
|
assert(p >= pData_);
|
||||||
|
|
||||||
|
unsigned char* toRelease = static_cast<unsigned char*>(p);
|
||||||
|
// Alignment check
|
||||||
|
assert((toRelease - pData_) % blockSize == 0);
|
||||||
|
|
||||||
|
*toRelease = firstAvailableBlock_;
|
||||||
|
firstAvailableBlock_ = static_cast<unsigned char>(
|
||||||
|
(toRelease - pData_) / blockSize);
|
||||||
|
// Truncation check
|
||||||
|
assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);
|
||||||
|
|
||||||
|
++blocksAvailable_;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::FixedAllocator
|
||||||
|
// Creates a FixedAllocator object of a fixed block size
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FixedAllocator::FixedAllocator(std::size_t blockSize)
|
||||||
|
: blockSize_(blockSize)
|
||||||
|
, allocChunk_(0)
|
||||||
|
, deallocChunk_(0)
|
||||||
|
{
|
||||||
|
assert(blockSize_ > 0);
|
||||||
|
|
||||||
|
prev_ = next_ = this;
|
||||||
|
|
||||||
|
std::size_t numBlocks = DEFAULT_CHUNK_SIZE / blockSize;
|
||||||
|
if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX;
|
||||||
|
else if (numBlocks == 0) numBlocks = 8 * blockSize;
|
||||||
|
|
||||||
|
numBlocks_ = static_cast<unsigned char>(numBlocks);
|
||||||
|
assert(numBlocks_ == numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::FixedAllocator(const FixedAllocator&)
|
||||||
|
// Creates a FixedAllocator object of a fixed block size
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FixedAllocator::FixedAllocator(const FixedAllocator& rhs)
|
||||||
|
: blockSize_(rhs.blockSize_)
|
||||||
|
, numBlocks_(rhs.numBlocks_)
|
||||||
|
, chunks_(rhs.chunks_)
|
||||||
|
{
|
||||||
|
prev_ = &rhs;
|
||||||
|
next_ = rhs.next_;
|
||||||
|
rhs.next_->prev_ = this;
|
||||||
|
rhs.next_ = this;
|
||||||
|
|
||||||
|
allocChunk_ = rhs.allocChunk_
|
||||||
|
? &chunks_.front() + (rhs.allocChunk_ - &rhs.chunks_.front())
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
deallocChunk_ = rhs.deallocChunk_
|
||||||
|
? &chunks_.front() + (rhs.deallocChunk_ - &rhs.chunks_.front())
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedAllocator& FixedAllocator::operator=(const FixedAllocator& rhs)
|
||||||
|
{
|
||||||
|
FixedAllocator copy(rhs);
|
||||||
|
copy.Swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::~FixedAllocator
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FixedAllocator::~FixedAllocator()
|
||||||
|
{
|
||||||
|
if (prev_ != this)
|
||||||
|
{
|
||||||
|
prev_->next_ = next_;
|
||||||
|
next_->prev_ = prev_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(prev_ == next_);
|
||||||
|
Chunks::iterator i = chunks_.begin();
|
||||||
|
for (; i != chunks_.end(); ++i)
|
||||||
|
{
|
||||||
|
assert(i->blocksAvailable_ == numBlocks_);
|
||||||
|
i->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Swap
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Swap(FixedAllocator& rhs)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
swap(blockSize_, rhs.blockSize_);
|
||||||
|
swap(numBlocks_, rhs.numBlocks_);
|
||||||
|
chunks_.swap(rhs.chunks_);
|
||||||
|
swap(allocChunk_, rhs.allocChunk_);
|
||||||
|
swap(deallocChunk_, rhs.deallocChunk_);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Allocate
|
||||||
|
// Allocates a block of fixed size
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* FixedAllocator::Allocate()
|
||||||
|
{
|
||||||
|
if (allocChunk_ == 0 || allocChunk_->blocksAvailable_ == 0)
|
||||||
|
{
|
||||||
|
Chunks::iterator i = chunks_.begin();
|
||||||
|
for (;; ++i)
|
||||||
|
{
|
||||||
|
if (i == chunks_.end())
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
chunks_.reserve(chunks_.size() + 1);
|
||||||
|
Chunk newChunk;
|
||||||
|
newChunk.Init(blockSize_, numBlocks_);
|
||||||
|
chunks_.push_back(newChunk);
|
||||||
|
allocChunk_ = &chunks_.back();
|
||||||
|
deallocChunk_ = &chunks_.front();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i->blocksAvailable_ > 0)
|
||||||
|
{
|
||||||
|
allocChunk_ = &*i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(allocChunk_ != 0);
|
||||||
|
assert(allocChunk_->blocksAvailable_ > 0);
|
||||||
|
|
||||||
|
return allocChunk_->Allocate(blockSize_);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::Deallocate
|
||||||
|
// Deallocates a block previously allocated with Allocate
|
||||||
|
// (undefined behavior if called with the wrong pointer)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::Deallocate(void* p)
|
||||||
|
{
|
||||||
|
assert(!chunks_.empty());
|
||||||
|
assert(&chunks_.front() <= deallocChunk_);
|
||||||
|
assert(&chunks_.back() >= deallocChunk_);
|
||||||
|
|
||||||
|
deallocChunk_ = VicinityFind(p);
|
||||||
|
assert(deallocChunk_);
|
||||||
|
|
||||||
|
DoDeallocate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::VicinityFind (internal)
|
||||||
|
// Finds the chunk corresponding to a pointer, using an efficient search
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p)
|
||||||
|
{
|
||||||
|
assert(!chunks_.empty());
|
||||||
|
assert(deallocChunk_);
|
||||||
|
|
||||||
|
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||||
|
|
||||||
|
Chunk* lo = deallocChunk_;
|
||||||
|
Chunk* hi = deallocChunk_ + 1;
|
||||||
|
Chunk* loBound = &chunks_.front();
|
||||||
|
Chunk* hiBound = &chunks_.back() + 1;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (lo)
|
||||||
|
{
|
||||||
|
if (p >= lo->pData_ && p < lo->pData_ + chunkLength)
|
||||||
|
{
|
||||||
|
return lo;
|
||||||
|
}
|
||||||
|
if (lo == loBound) lo = 0;
|
||||||
|
else --lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hi)
|
||||||
|
{
|
||||||
|
if (p >= hi->pData_ && p < hi->pData_ + chunkLength)
|
||||||
|
{
|
||||||
|
return hi;
|
||||||
|
}
|
||||||
|
if (++hi == hiBound) hi = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert(false);
|
||||||
|
// return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FixedAllocator::DoDeallocate (internal)
|
||||||
|
// Performs deallocation. Assumes deallocChunk_ points to the correct chunk
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FixedAllocator::DoDeallocate(void* p)
|
||||||
|
{
|
||||||
|
assert(deallocChunk_->pData_ <= p);
|
||||||
|
assert(deallocChunk_->pData_ + numBlocks_ * blockSize_ > p);
|
||||||
|
|
||||||
|
// call into the chunk, will adjust the inner list but won't release memory
|
||||||
|
deallocChunk_->Deallocate(p, blockSize_);
|
||||||
|
|
||||||
|
if (deallocChunk_->blocksAvailable_ == numBlocks_)
|
||||||
|
{
|
||||||
|
// deallocChunk_ is completely free, should we release it?
|
||||||
|
|
||||||
|
Chunk& lastChunk = chunks_.back();
|
||||||
|
|
||||||
|
if (&lastChunk == deallocChunk_)
|
||||||
|
{
|
||||||
|
// check if we have two last chunks empty
|
||||||
|
|
||||||
|
if (chunks_.size() > 1 &&
|
||||||
|
deallocChunk_[-1].blocksAvailable_ == numBlocks_)
|
||||||
|
{
|
||||||
|
// Two free chunks, discard the last one
|
||||||
|
lastChunk.Release();
|
||||||
|
chunks_.pop_back();
|
||||||
|
allocChunk_ = deallocChunk_ = &chunks_.front();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastChunk.blocksAvailable_ == numBlocks_)
|
||||||
|
{
|
||||||
|
// Two free blocks, discard one
|
||||||
|
lastChunk.Release();
|
||||||
|
chunks_.pop_back();
|
||||||
|
allocChunk_ = deallocChunk_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// move the empty chunk to the end
|
||||||
|
std::swap(*deallocChunk_, lastChunk);
|
||||||
|
allocChunk_ = &chunks_.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SmallObjAllocator::SmallObjAllocator
|
||||||
|
// Creates an allocator for small objects given chunk size and maximum 'small'
|
||||||
|
// object size
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SmallObjAllocator::SmallObjAllocator(
|
||||||
|
std::size_t chunkSize,
|
||||||
|
std::size_t maxObjectSize)
|
||||||
|
: pLastAlloc_(0), pLastDealloc_(0)
|
||||||
|
, chunkSize_(chunkSize), maxObjectSize_(maxObjectSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SmallObjAllocator::Allocate
|
||||||
|
// Allocates 'numBytes' memory
|
||||||
|
// Uses an internal pool of FixedAllocator objects for small objects
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* SmallObjAllocator::Allocate(std::size_t numBytes)
|
||||||
|
{
|
||||||
|
if (numBytes > maxObjectSize_) return operator new(numBytes);
|
||||||
|
|
||||||
|
if (pLastAlloc_ && pLastAlloc_->BlockSize() == numBytes)
|
||||||
|
{
|
||||||
|
return pLastAlloc_->Allocate();
|
||||||
|
}
|
||||||
|
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||||
|
if (i == pool_.end() || i->BlockSize() != numBytes)
|
||||||
|
{
|
||||||
|
i = pool_.insert(i, FixedAllocator(numBytes));
|
||||||
|
pLastDealloc_ = &*pool_.begin();
|
||||||
|
}
|
||||||
|
pLastAlloc_ = &*i;
|
||||||
|
return pLastAlloc_->Allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SmallObjAllocator::Deallocate
|
||||||
|
// Deallocates memory previously allocated with Allocate
|
||||||
|
// (undefined behavior if you pass any other pointer)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SmallObjAllocator::Deallocate(void* p, std::size_t numBytes)
|
||||||
|
{
|
||||||
|
if (numBytes > maxObjectSize_) return operator delete(p);
|
||||||
|
|
||||||
|
if (pLastDealloc_ && pLastDealloc_->BlockSize() == numBytes)
|
||||||
|
{
|
||||||
|
pLastDealloc_->Deallocate(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||||
|
assert(i != pool_.end());
|
||||||
|
assert(i->BlockSize() == numBytes);
|
||||||
|
pLastDealloc_ = &*i;
|
||||||
|
pLastDealloc_->Deallocate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// March 20: fix exception safety issue in FixedAllocator::Allocate
|
||||||
|
// (thanks to Chris Udazvinis for pointing that out)
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
211
MSVC/1300/SmallObj.h
Normal file
211
MSVC/1300/SmallObj.h
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef SMALLOBJ_INC_
|
||||||
|
#define SMALLOBJ_INC_
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
#include "Singleton.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef DEFAULT_CHUNK_SIZE
|
||||||
|
#define DEFAULT_CHUNK_SIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_SMALL_OBJECT_SIZE
|
||||||
|
#define MAX_SMALL_OBJECT_SIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class FixedAllocator
|
||||||
|
// Offers services for allocating fixed-sized objects
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FixedAllocator
|
||||||
|
{
|
||||||
|
public: // VC7 access control BUG
|
||||||
|
class Chunk
|
||||||
|
{
|
||||||
|
friend FixedAllocator;
|
||||||
|
|
||||||
|
void Init(std::size_t blockSize, unsigned char blocks);
|
||||||
|
void* Allocate(std::size_t blockSize);
|
||||||
|
void Deallocate(void* p, std::size_t blockSize);
|
||||||
|
void Reset(std::size_t blockSize, unsigned char blocks);
|
||||||
|
void Release();
|
||||||
|
unsigned char* pData_;
|
||||||
|
unsigned char
|
||||||
|
firstAvailableBlock_,
|
||||||
|
blocksAvailable_;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Internal functions
|
||||||
|
void DoDeallocate(void* p);
|
||||||
|
Chunk* VicinityFind(void* p);
|
||||||
|
|
||||||
|
// Data
|
||||||
|
std::size_t blockSize_;
|
||||||
|
unsigned char numBlocks_;
|
||||||
|
typedef std::vector<Chunk> Chunks;
|
||||||
|
Chunks chunks_;
|
||||||
|
Chunk* allocChunk_;
|
||||||
|
Chunk* deallocChunk_;
|
||||||
|
// For ensuring proper copy semantics
|
||||||
|
mutable const FixedAllocator* prev_;
|
||||||
|
mutable const FixedAllocator* next_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Create a FixedAllocator able to manage blocks of 'blockSize' size
|
||||||
|
explicit FixedAllocator(std::size_t blockSize = 0);
|
||||||
|
FixedAllocator(const FixedAllocator&);
|
||||||
|
FixedAllocator& operator=(const FixedAllocator&);
|
||||||
|
~FixedAllocator();
|
||||||
|
|
||||||
|
void Swap(FixedAllocator& rhs);
|
||||||
|
|
||||||
|
// Allocate a memory block
|
||||||
|
void* Allocate();
|
||||||
|
// Deallocate a memory block previously allocated with Allocate()
|
||||||
|
// (if that's not the case, the behavior is undefined)
|
||||||
|
void Deallocate(void* p);
|
||||||
|
// Returns the block size with which the FixedAllocator was initialized
|
||||||
|
std::size_t BlockSize() const
|
||||||
|
{ return blockSize_; }
|
||||||
|
// Comparison operator for sorting
|
||||||
|
bool operator<(std::size_t rhs) const
|
||||||
|
{ return BlockSize() < rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class SmallObjAllocator
|
||||||
|
// Offers services for allocating small-sized objects
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SmallObjAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SmallObjAllocator(
|
||||||
|
std::size_t chunkSize,
|
||||||
|
std::size_t maxObjectSize);
|
||||||
|
|
||||||
|
void* Allocate(std::size_t numBytes);
|
||||||
|
void Deallocate(void* p, std::size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SmallObjAllocator(const SmallObjAllocator&);
|
||||||
|
SmallObjAllocator& operator=(const SmallObjAllocator&);
|
||||||
|
|
||||||
|
typedef std::vector<FixedAllocator> Pool;
|
||||||
|
Pool pool_;
|
||||||
|
FixedAllocator* pLastAlloc_;
|
||||||
|
FixedAllocator* pLastDealloc_;
|
||||||
|
std::size_t chunkSize_;
|
||||||
|
std::size_t maxObjectSize_;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class SmallObject
|
||||||
|
// Base class for polymorphic small objects, offers fast
|
||||||
|
// allocations/deallocations
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class ClientType,
|
||||||
|
class ThreadingModelType
|
||||||
|
>
|
||||||
|
class SmallObjectStaticData
|
||||||
|
{
|
||||||
|
friend ClientType; // illegal (11.4/2) but works with VC
|
||||||
|
static ThreadingModelType s_ThreadingModelData;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class C, class M>
|
||||||
|
M SmallObjectStaticData<C, M>::s_ThreadingModelData;
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
template <class> class ThreadingModel = DEFAULT_THREADING,
|
||||||
|
std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
|
||||||
|
std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
|
||||||
|
>
|
||||||
|
class SmallObject : public ThreadingModel<
|
||||||
|
SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
|
||||||
|
{
|
||||||
|
typedef ThreadingModel< SmallObject<ThreadingModel,
|
||||||
|
chunkSize, maxSmallObjectSize> > MyThreadingModel;
|
||||||
|
|
||||||
|
typedef SmallObjectStaticData
|
||||||
|
<
|
||||||
|
SmallObject,
|
||||||
|
MyThreadingModel
|
||||||
|
>
|
||||||
|
MySmallObjectStaticData;
|
||||||
|
|
||||||
|
struct MySmallObjAllocator : public SmallObjAllocator
|
||||||
|
{
|
||||||
|
MySmallObjAllocator()
|
||||||
|
: SmallObjAllocator(chunkSize, maxSmallObjectSize)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
// The typedef below would make things much simpler,
|
||||||
|
// but MWCW won't like it
|
||||||
|
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
|
||||||
|
// DefaultLifetime, ThreadingModel*/> MyAllocator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void* operator new(std::size_t size)
|
||||||
|
{
|
||||||
|
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||||
|
typename MyThreadingModel::Lock lock(
|
||||||
|
MySmallObjectStaticData::s_ThreadingModelData);
|
||||||
|
(void)lock; // get rid of warning
|
||||||
|
|
||||||
|
return SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||||
|
PhoenixSingleton>::Instance().Allocate(size);
|
||||||
|
#else
|
||||||
|
return ::operator new(size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static void operator delete(void* p, std::size_t size)
|
||||||
|
{
|
||||||
|
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||||
|
typename MyThreadingModel::Lock lock(
|
||||||
|
MySmallObjectStaticData::s_ThreadingModelData);
|
||||||
|
(void)lock; // get rid of warning
|
||||||
|
|
||||||
|
SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||||
|
PhoenixSingleton>::Instance().Deallocate(p, size);
|
||||||
|
#else
|
||||||
|
::operator delete(p, size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
virtual ~SmallObject() {}
|
||||||
|
};
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // SMALLOBJ_INC_
|
1329
MSVC/1300/SmartPtr.h
Normal file
1329
MSVC/1300/SmartPtr.h
Normal file
File diff suppressed because it is too large
Load diff
202
MSVC/1300/Threads.h
Normal file
202
MSVC/1300/Threads.h
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#ifndef THREADS_H_
|
||||||
|
#define THREADS_H_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// macro DEFAULT_THREADING
|
||||||
|
// Selects the default threading model for certain components of Loki
|
||||||
|
// If you don't define it, it defaults to single-threaded
|
||||||
|
// All classes in Loki have configurable threading model; DEFAULT_THREADING
|
||||||
|
// affects only default template arguments
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: June 20, 2001
|
||||||
|
|
||||||
|
#ifndef DEFAULT_THREADING
|
||||||
|
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template SingleThreaded
|
||||||
|
// Implementation of the ThreadingModel policy used by various classes
|
||||||
|
// Implements a single-threaded model; no synchronization
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Host>
|
||||||
|
class SingleThreaded
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Lock
|
||||||
|
{
|
||||||
|
Lock() {}
|
||||||
|
explicit Lock(const SingleThreaded&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Host VolatileType;
|
||||||
|
|
||||||
|
typedef int IntType;
|
||||||
|
|
||||||
|
static IntType AtomicAdd(volatile IntType& lval, IntType val)
|
||||||
|
{ return lval += val; }
|
||||||
|
|
||||||
|
static IntType AtomicSubtract(volatile IntType& lval, IntType val)
|
||||||
|
{ return lval -= val; }
|
||||||
|
|
||||||
|
static IntType AtomicMultiply(volatile IntType& lval, IntType val)
|
||||||
|
{ return lval *= val; }
|
||||||
|
|
||||||
|
static IntType AtomicDivide(volatile IntType& lval, IntType val)
|
||||||
|
{ return lval /= val; }
|
||||||
|
|
||||||
|
static IntType AtomicIncrement(volatile IntType& lval)
|
||||||
|
{ return ++lval; }
|
||||||
|
|
||||||
|
static IntType AtomicDecrement(volatile IntType& lval)
|
||||||
|
{ return --lval; }
|
||||||
|
|
||||||
|
static IntType AtomicDivide(volatile IntType& lval)
|
||||||
|
{ return lval /= val; }
|
||||||
|
|
||||||
|
static void AtomicAssign(volatile IntType & lval, IntType val)
|
||||||
|
{ lval = val; }
|
||||||
|
|
||||||
|
static void AtomicAssign(IntType & lval, volatile IntType & val)
|
||||||
|
{ lval = val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _WINDOWS_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template ObjectLevelLockable
|
||||||
|
// Implementation of the ThreadingModel policy used by various classes
|
||||||
|
// Implements a object-level locking scheme
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Host>
|
||||||
|
class ObjectLevelLockable
|
||||||
|
{
|
||||||
|
CRITICAL_SECTION mtx_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ObjectLevelLockable()
|
||||||
|
{
|
||||||
|
::InitializeCriticalSection(&mtx_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ObjectLevelLockable()
|
||||||
|
{
|
||||||
|
::DeleteCriticalSection(&mtx_);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lock;
|
||||||
|
friend class Lock;
|
||||||
|
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
|
ObjectLevelLockable& host_;
|
||||||
|
|
||||||
|
Lock(const Lock&);
|
||||||
|
Lock& operator=(const Lock&);
|
||||||
|
Lock(); // buggy design
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Lock(ObjectLevelLockable& host) : host_(host)
|
||||||
|
{
|
||||||
|
::EnterCriticalSection(&host_.mtx_);
|
||||||
|
}
|
||||||
|
~Lock()
|
||||||
|
{
|
||||||
|
::LeaveCriticalSection(&host_.mtx_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef volatile Host VolatileType;
|
||||||
|
|
||||||
|
typedef LONG IntType;
|
||||||
|
|
||||||
|
static IntType AtomicIncrement(volatile IntType& lval)
|
||||||
|
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||||
|
|
||||||
|
static IntType AtomicDecrement(volatile IntType& lval)
|
||||||
|
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
|
||||||
|
|
||||||
|
static void AtomicAssign(volatile IntType& lval, IntType val)
|
||||||
|
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
|
||||||
|
|
||||||
|
static void AtomicAssign(IntType& lval, volatile IntType& val)
|
||||||
|
{ InterlockedExchange(&lval, val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Host>
|
||||||
|
class ClassLevelLockable
|
||||||
|
{
|
||||||
|
struct Initializer
|
||||||
|
{
|
||||||
|
CRITICAL_SECTION mtx_;
|
||||||
|
|
||||||
|
Initializer()
|
||||||
|
{
|
||||||
|
::InitializeCriticalSection(&mtx_);
|
||||||
|
}
|
||||||
|
~Initializer()
|
||||||
|
{
|
||||||
|
::DeleteCriticalSection(&mtx_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Initializer initializer_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
class Lock;
|
||||||
|
friend class Lock;
|
||||||
|
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
|
Lock(const Lock&);
|
||||||
|
Lock& operator=(const Lock&);
|
||||||
|
public:
|
||||||
|
Lock()
|
||||||
|
{
|
||||||
|
::EnterCriticalSection(&initializer_.mtx_);
|
||||||
|
}
|
||||||
|
explicit Lock(ClassLevelLockable&)
|
||||||
|
{
|
||||||
|
::EnterCriticalSection(&initializer_.mtx_);
|
||||||
|
}
|
||||||
|
~Lock()
|
||||||
|
{
|
||||||
|
::LeaveCriticalSection(&initializer_.mtx_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef volatile Host VolatileType;
|
||||||
|
|
||||||
|
typedef LONG IntType;
|
||||||
|
|
||||||
|
static IntType AtomicIncrement(volatile IntType& lval)
|
||||||
|
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||||
|
|
||||||
|
static IntType AtomicDecrement(volatile IntType& lval)
|
||||||
|
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
|
||||||
|
|
||||||
|
static void AtomicAssign(volatile IntType& lval, IntType val)
|
||||||
|
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
|
||||||
|
|
||||||
|
static void AtomicAssign(IntType& lval, volatile IntType& val)
|
||||||
|
{ InterlockedExchange(&lval, val); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Host>
|
||||||
|
typename ClassLevelLockable<Host>::Initializer
|
||||||
|
ClassLevelLockable<Host>::initializer_;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,12 +13,7 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: June 20, 2001
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
// MKH
|
|
||||||
// Copy of TypeInfo.h made to that #include "Typelist.h" gets the local
|
|
||||||
// flavor instead of the reference implementation
|
|
||||||
// Added a couple of #pramga warning(disable:4800) becase we just don't care.
|
|
||||||
|
|
||||||
#ifndef TYPEINFO_INC_
|
#ifndef TYPEINFO_INC_
|
||||||
#define TYPEINFO_INC_
|
#define TYPEINFO_INC_
|
||||||
|
@ -67,10 +62,7 @@ namespace Loki
|
||||||
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
||||||
{
|
{
|
||||||
assert(pInfo_);
|
assert(pInfo_);
|
||||||
#pragma warning(push)
|
return pInfo_->before(*rhs.pInfo_) != 0;
|
||||||
#pragma warning(disable: 4800)
|
|
||||||
return pInfo_->before(*rhs.pInfo_);
|
|
||||||
#pragma warning(pop)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_info& TypeInfo::Get() const
|
inline const std::type_info& TypeInfo::Get() const
|
||||||
|
@ -88,12 +80,7 @@ namespace Loki
|
||||||
// Comparison operators
|
// Comparison operators
|
||||||
|
|
||||||
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
{
|
{ return (lhs.Get() == rhs.Get()) != 0; }
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4800)
|
|
||||||
return lhs.Get() == rhs.Get();
|
|
||||||
#pragma warning(pop)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||||
{ return lhs.before(rhs); }
|
{ return lhs.before(rhs); }
|
||||||
|
@ -114,6 +101,7 @@ namespace Loki
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // TYPEINFO_INC_
|
#endif // TYPEINFO_INC_
|
||||||
|
|
|
@ -13,12 +13,13 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: August 22, 2001
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
#ifndef TYPELIST_INC_
|
#ifndef TYPELIST_INC_
|
||||||
#define TYPELIST_INC_
|
#define TYPELIST_INC_
|
||||||
|
|
||||||
#include "NullType.h"
|
#include "static_check.h"
|
||||||
|
#include "Nulltype.h"
|
||||||
#include "TypeManip.h"
|
#include "TypeManip.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -301,7 +302,7 @@
|
||||||
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
|
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
|
||||||
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
|
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
|
||||||
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
|
T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
|
||||||
T41, T42, T43, T44, T45) >
|
T41, T42, T43, T44, T45, T46) >
|
||||||
|
|
||||||
#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
|
#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
|
||||||
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
|
T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
|
||||||
|
@ -367,6 +368,122 @@ namespace Loki
|
||||||
|
|
||||||
namespace TL
|
namespace TL
|
||||||
{
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template MakeTypelist
|
||||||
|
// Takes a number of arguments equal to its numeric suffix
|
||||||
|
// The arguments are type names.
|
||||||
|
// MakeTypeList<T1, T2, ...>::Result
|
||||||
|
// returns a typelist that is of T1, T2, ...
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
|
||||||
|
typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
|
||||||
|
typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
|
||||||
|
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
|
||||||
|
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
|
||||||
|
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
|
||||||
|
>
|
||||||
|
struct MakeTypeList
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename MakeTypeList
|
||||||
|
<
|
||||||
|
T2 , T3 , T4 ,
|
||||||
|
T5 , T6 , T7 ,
|
||||||
|
T8 , T9 , T10,
|
||||||
|
T11, T12, T13,
|
||||||
|
T14, T15, T16,
|
||||||
|
T17, T18
|
||||||
|
>
|
||||||
|
::Result TailResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Typelist<T1, TailResult> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct MakeTypeList
|
||||||
|
<
|
||||||
|
NullType, NullType, NullType,
|
||||||
|
NullType, NullType, NullType,
|
||||||
|
NullType, NullType, NullType,
|
||||||
|
NullType, NullType, NullType,
|
||||||
|
NullType, NullType, NullType,
|
||||||
|
NullType, NullType, NullType
|
||||||
|
>{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template is_Typelist
|
||||||
|
// detects if type is Typelist (including Nulltype)
|
||||||
|
// Invocation :
|
||||||
|
// is_Typelist<T>::value
|
||||||
|
// returns a compile-time boolean constant containing true iff T is some Typelist<T1,T2>
|
||||||
|
// is_Typelist<T>::type_id
|
||||||
|
// returns a compile-time unsigned constant containing
|
||||||
|
// 1 iff T == Typelist<T1,T2>, 2 iff T == NullType and 3 otherwise
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct Typelist_tag {};
|
||||||
|
struct NullType_tag {};
|
||||||
|
struct NoneList_tag {};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Typelist_ID = 1,
|
||||||
|
NullType_ID = 2,
|
||||||
|
NoneList_ID = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_Typelist
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef char (&ye1)[Typelist_ID];
|
||||||
|
typedef char (&ye2)[NullType_ID];
|
||||||
|
typedef char (&no) [NoneList_ID];
|
||||||
|
|
||||||
|
template<typename Head, typename Tail>
|
||||||
|
static ye1 check(Type2Type< Typelist<Head, Tail> >);
|
||||||
|
static ye2 check(Type2Type<NullType>);
|
||||||
|
|
||||||
|
static no check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// VC7 fail NPS_HierarchyGenerators.h if this one is enum
|
||||||
|
static const unsigned int type_id = sizeof(check( Type2Type<T>() ));
|
||||||
|
|
||||||
|
enum { value = type_id != sizeof(no) };
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
type_id == Typelist_ID,
|
||||||
|
Typelist_tag,
|
||||||
|
typename Select<type_id == NullType_ID, NullType_tag, NoneList_tag>::Result
|
||||||
|
>
|
||||||
|
::Result type_tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TL_FAST_COMPILATION
|
||||||
|
|
||||||
|
// this macro will cause compile time error if _type_ is not a Typelist or NullType
|
||||||
|
#define ASSERT_TYPELIST(_type_) \
|
||||||
|
STATIC_CHECK( ::Loki::TL::is_Typelist<_type_>::value, TList_is_not_legal_Typelist )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// might improve the compilation time
|
||||||
|
#define ASSERT_TYPELIST(_type_) \
|
||||||
|
typedef char _type_##_is_not_a_Typelist[true]
|
||||||
|
|
||||||
|
#endif // ndef TL_FAST_COMPILATION
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Length
|
// class template Length
|
||||||
// Computes the length of a typelist
|
// Computes the length of a typelist
|
||||||
|
@ -375,24 +492,11 @@ namespace Loki
|
||||||
// returns a compile-time constant containing the length of TList, not counting
|
// returns a compile-time constant containing the length of TList, not counting
|
||||||
// the end terminator (which by convention is NullType)
|
// the end terminator (which by convention is NullType)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//*
|
|
||||||
namespace Length_
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
struct HeadLength
|
|
||||||
{
|
|
||||||
enum { value = 1 };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct HeadLength<NullType>
|
|
||||||
{
|
|
||||||
enum { value = 0 };
|
|
||||||
};
|
|
||||||
}//ns TL::Length_
|
|
||||||
//*/
|
|
||||||
template <class TList> struct Length;
|
template <class TList> struct Length;
|
||||||
template <> struct Length<NullType>
|
|
||||||
|
template <>
|
||||||
|
struct Length<NullType>
|
||||||
{
|
{
|
||||||
enum { value = 0 };
|
enum { value = 0 };
|
||||||
};
|
};
|
||||||
|
@ -400,11 +504,16 @@ namespace Loki
|
||||||
template <class TList>
|
template <class TList>
|
||||||
struct Length
|
struct Length
|
||||||
{
|
{
|
||||||
enum { value = (Length_::HeadLength<typename TList::Head>::value
|
private:
|
||||||
+
|
ASSERT_TYPELIST(TList);
|
||||||
Length<typename TList::Tail>::value) };
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum { value = 1 + Length<Tail>::value };
|
||||||
};
|
};
|
||||||
//*/
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template TypeAt
|
// class template TypeAt
|
||||||
// Finds the type at a given index in a typelist
|
// Finds the type at a given index in a typelist
|
||||||
|
@ -415,31 +524,31 @@ namespace Loki
|
||||||
// If you pass an out-of-bounds index, the result is a compile-time error
|
// If you pass an out-of-bounds index, the result is a compile-time error
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace TypeAt_ {
|
template <class TList, unsigned int index>
|
||||||
|
struct TypeAt
|
||||||
|
{
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
template<unsigned int i>
|
template<unsigned int i>
|
||||||
struct Index {
|
struct In
|
||||||
template<class TList>
|
{
|
||||||
struct Which {
|
typedef typename TypeAt<Tail, i - 1>::Result Result;
|
||||||
typedef typename Index<i - 1>::Which<typename TList::Tail>::Result Result;
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Index<0> {
|
struct In<0>
|
||||||
template<class TList>
|
{
|
||||||
struct Which {
|
typedef Head Result;
|
||||||
typedef typename TList::Head Result;
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TypeAt_
|
|
||||||
|
|
||||||
template<class TList, unsigned int i>
|
|
||||||
struct TypeAt {
|
|
||||||
typedef typename TypeAt_::Index<i>::Which<TList>::Result Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<index>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template TypeAtNonStrict
|
// class template TypeAtNonStrict
|
||||||
// Finds the type at a given index in a typelist
|
// Finds the type at a given index in a typelist
|
||||||
|
@ -452,55 +561,42 @@ namespace Loki
|
||||||
// returns the type in position 'index' in TList, or D if index is out-of-bounds
|
// returns the type in position 'index' in TList, or D if index is out-of-bounds
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace TypeAtNonStrict_ {
|
|
||||||
|
|
||||||
template<class TList>
|
template <class TList, unsigned int index, typename DefaultType = NullType>
|
||||||
struct ListType;
|
struct TypeAtNonStrict
|
||||||
|
{
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
template<unsigned int index>
|
template<class TList1,unsigned int i>
|
||||||
struct Index;
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename TypeAtNonStrict
|
||||||
|
<
|
||||||
|
typename TList1::Tail,
|
||||||
|
i - 1,
|
||||||
|
DefaultType
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ListType<NullType> {
|
struct In<Typelist<Head, Tail>, 0>
|
||||||
template<unsigned int index, typename DefaultType>
|
{
|
||||||
struct Remainder {
|
typedef Head Result;
|
||||||
typedef DefaultType Result;
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Index<0> {
|
struct In<NullType, index>
|
||||||
template<class TList, typename DefaultType>
|
{
|
||||||
struct Remainder {
|
typedef DefaultType Result;
|
||||||
typedef typename TList::Head Result;
|
};
|
||||||
};
|
public:
|
||||||
};
|
typedef typename In<TList, index>::Result Result;
|
||||||
|
};
|
||||||
template<unsigned int index>
|
|
||||||
struct Index {
|
|
||||||
template<class TList, typename DefaultType>
|
|
||||||
struct Remainder {
|
|
||||||
enum { isSameType = Conversion<NullType, typename TList::Tail>::sameType };
|
|
||||||
typedef typename Select<isSameType, NullType, typename Index<index - 1>::Remainder<typename TList::Tail, DefaultType>::Result>::Result Result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class TList>
|
|
||||||
struct ListType {
|
|
||||||
template<unsigned int index, typename DefaultType>
|
|
||||||
struct Remainder {
|
|
||||||
typedef typename Index<index>::Remainder<TList, DefaultType>::Result Result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TypeAtNonStrict_
|
|
||||||
|
|
||||||
template<class TList, unsigned int index, typename DefaultType = NullType>
|
|
||||||
struct TypeAtNonStrict {
|
|
||||||
typedef typename TypeAtNonStrict_::ListType<TList>::Remainder<index, DefaultType>::Result Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TL
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template IndexOf
|
// class template IndexOf
|
||||||
|
@ -510,67 +606,43 @@ namespace Loki
|
||||||
// returns the position of T in TList, or NullType if T is not found in TList
|
// returns the position of T in TList, or NullType if T is not found in TList
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Private {
|
template <class TList, class T>
|
||||||
|
struct IndexOf
|
||||||
|
{
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
namespace IndexOf_ {
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
|
||||||
template<typename TList>
|
enum { temp = (IndexOf<Tail, T>::value) };
|
||||||
struct Head {
|
|
||||||
typedef typename TList::Head Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
public:
|
||||||
struct Head<NullType> {
|
enum { value = temp == -1 ? -1 : 1 + temp };
|
||||||
typedef void Result;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct IsNull {
|
template<>
|
||||||
enum { value = -1 };
|
struct In< Typelist<T, Tail> >
|
||||||
};
|
{
|
||||||
|
enum { value = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
struct IsTHead {
|
template<>
|
||||||
enum { value = 0 };
|
struct In<NullType>
|
||||||
};
|
{
|
||||||
|
enum { value = -1 };
|
||||||
|
};
|
||||||
|
|
||||||
template<typename TList, typename T>
|
public:
|
||||||
struct IsNotTHead {
|
enum { value = In<TList>::value };
|
||||||
typedef typename TList::Tail Tail;
|
};
|
||||||
typedef typename Select<is_same<Tail, NullType>::result,
|
|
||||||
IsNull,
|
|
||||||
typename Select<is_same<typename Head<Tail>::Result, T>::result,
|
|
||||||
IsTHead, IsNotTHead<Tail, T>
|
|
||||||
>::Result
|
|
||||||
>::Result chooser;
|
|
||||||
enum { temp = chooser::value };
|
|
||||||
enum { value = temp == -1 ? -1 : 1 + temp };
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TList, typename T>
|
|
||||||
struct IsNotNull {
|
|
||||||
typedef typename Select<is_same<typename TList::Head, T>::result,
|
|
||||||
IsTHead,
|
|
||||||
IsNotTHead<TList, T>
|
|
||||||
>::Result chooser;
|
|
||||||
enum { value = chooser::value };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace IndexOf_
|
|
||||||
|
|
||||||
} // namespace Private
|
|
||||||
|
|
||||||
namespace TL {
|
|
||||||
|
|
||||||
template<class TList, class T>
|
|
||||||
struct IndexOf {
|
|
||||||
private:
|
|
||||||
typedef typename Select<Private::is_same<TList, NullType>::result,
|
|
||||||
Private::IndexOf_::IsNull,
|
|
||||||
Private::IndexOf_::IsNotNull<TList, T>
|
|
||||||
>::Result chooser;
|
|
||||||
public:
|
|
||||||
enum { value = chooser::value };
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Append
|
// class template Append
|
||||||
// Appends a type or a typelist to another
|
// Appends a type or a typelist to another
|
||||||
|
@ -579,37 +651,42 @@ public:
|
||||||
// returns a typelist that is TList followed by T and NullType-terminated
|
// returns a typelist that is TList followed by T and NullType-terminated
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Append_ {
|
template <class TList, class T>
|
||||||
|
struct Append
|
||||||
template<class T>
|
{
|
||||||
struct Helper {
|
typedef typename TList::Head Head;
|
||||||
struct big { char i[2]; };
|
typedef typename TList::Tail Tail;
|
||||||
template<class Head, class Tail>
|
|
||||||
static char Test(const Typelist<Head, Tail>&);
|
|
||||||
static big Test(...);
|
|
||||||
static T makeT();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Append_
|
|
||||||
|
|
||||||
template<class TList, class T>
|
|
||||||
struct Append;
|
|
||||||
|
|
||||||
template<>
|
private:
|
||||||
struct Append<NullType, NullType> {
|
ASSERT_TYPELIST(TList);
|
||||||
typedef NullType Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class TList, class T>
|
template<class TList1>
|
||||||
struct Append {
|
struct In
|
||||||
private:
|
{
|
||||||
enum { T_is_list = sizeof(Append_::Helper<T>::Test(Append_::Helper<T>::MakeT())) == sizeof(char) };
|
typedef typename TList1::Tail Tail;
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
|
||||||
typedef typename Select<TList_is_null & T_is_list, T, NullType>::Result Result1;
|
typedef Typelist
|
||||||
typedef typename Select<TList_is_null & !T_is_list, Typelist<T, NullType>, Result1>::Result Result2;
|
<
|
||||||
public:
|
Head,
|
||||||
typedef typename Select<!TList_is_null & !T_is_list, Typelist<typename TList::Head, typename Append<typename TList::Tail, T>::Result>, Result2>::Result Result;
|
typename Append<Tail, T>::Result
|
||||||
};
|
>
|
||||||
|
Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
is_Typelist<T>::value,
|
||||||
|
T, TYPELIST_1(T)
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Erase
|
// class template Erase
|
||||||
|
@ -619,15 +696,43 @@ public:
|
||||||
// returns a typelist that is TList without the first occurence of T
|
// returns a typelist that is TList without the first occurence of T
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList, class T>
|
template <class TList, class T>
|
||||||
struct Erase {
|
struct Erase
|
||||||
private:
|
{
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
typedef typename TList::Head Head;
|
||||||
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
|
typedef typename TList::Tail Tail;
|
||||||
typedef typename Select<!TList_is_null & Head_is_T, typename TList::Tail, NullType>::Result Result1;
|
|
||||||
public:
|
private:
|
||||||
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Erase<typename TList::Tail, T>::Result>, Result1>::Result Result;
|
ASSERT_TYPELIST(TList);
|
||||||
};
|
|
||||||
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
|
||||||
|
typedef Typelist
|
||||||
|
<
|
||||||
|
Head,
|
||||||
|
typename Erase<Tail, T>::Result
|
||||||
|
>
|
||||||
|
Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In< Typelist<T, Tail> >
|
||||||
|
{
|
||||||
|
typedef Tail Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template EraseAll
|
// class template EraseAll
|
||||||
|
@ -637,15 +742,41 @@ public:
|
||||||
// returns a typelist that is TList without any occurence of T
|
// returns a typelist that is TList without any occurence of T
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList, class T>
|
template <class TList, class T>
|
||||||
struct EraseAll {
|
struct EraseAll
|
||||||
private:
|
{
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
typedef typename TList::Head Head;
|
||||||
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
|
typedef typename TList::Tail Tail;
|
||||||
typedef typename Select<!TList_is_null & Head_is_T, typename EraseAll<typename TList::Tail, T>::Result, NullType>::Result Result1;
|
|
||||||
public:
|
private:
|
||||||
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename EraseAll<typename TList::Tail, T>::Result>, Result1>::Result Result;
|
ASSERT_TYPELIST(TList);
|
||||||
};
|
|
||||||
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
typedef typename EraseAll<Tail, T>::Result TailResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
SameType<Head, T>::value,
|
||||||
|
TailResult,
|
||||||
|
Typelist<Head, TailResult>
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template NoDuplicates
|
// class template NoDuplicates
|
||||||
|
@ -654,23 +785,27 @@ public:
|
||||||
// NoDuplicates<TList, T>::Result
|
// NoDuplicates<TList, T>::Result
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList>
|
template <class TList>
|
||||||
struct NoDuplicates;
|
struct NoDuplicates
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
template<>
|
typedef typename NoDuplicates<Tail>::Result L1;
|
||||||
struct NoDuplicates<NullType> {
|
typedef typename Erase<L1, Head>::Result L2;
|
||||||
typedef NullType Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class TList>
|
|
||||||
struct NoDuplicates {
|
|
||||||
private:
|
|
||||||
typedef typename NoDuplicates<typename TList::Tail>::Result L1;
|
|
||||||
typedef typename Erase<L1, typename TList::Head>::Result L2;
|
|
||||||
public:
|
|
||||||
typedef Typelist<typename TList::Head, L2> Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Typelist<Head, L2> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct NoDuplicates<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Replace
|
// class template Replace
|
||||||
|
@ -680,16 +815,44 @@ public:
|
||||||
// returns a typelist in which the first occurence of T is replaced with U
|
// returns a typelist in which the first occurence of T is replaced with U
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList, class T, class U>
|
template <class TList, class T, class U>
|
||||||
struct Replace {
|
struct Replace
|
||||||
private:
|
{
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
typedef typename TList::Head Head;
|
||||||
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
|
typedef typename TList::Tail Tail;
|
||||||
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename TList::Tail>, NullType>::Result Result1;
|
|
||||||
public:
|
|
||||||
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename Replace<typename TList::Tail, T, U>::Result>, Result1>::Result Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
|
||||||
|
typedef Typelist
|
||||||
|
<
|
||||||
|
Head,
|
||||||
|
typename Replace<Tail, T, U>::Result
|
||||||
|
>
|
||||||
|
Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In< Typelist<T, Tail> >
|
||||||
|
{
|
||||||
|
typedef Typelist<U, Tail> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template ReplaceAll
|
// class template ReplaceAll
|
||||||
// Replaces all occurences of a type in a typelist, with another type
|
// Replaces all occurences of a type in a typelist, with another type
|
||||||
|
@ -698,16 +861,42 @@ public:
|
||||||
// returns a typelist in which all occurences of T is replaced with U
|
// returns a typelist in which all occurences of T is replaced with U
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList, class T, class U>
|
template <class TList, class T, class U>
|
||||||
struct ReplaceAll {
|
struct ReplaceAll
|
||||||
private:
|
{
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
typedef typename TList::Head Head;
|
||||||
enum { Head_is_T = Conversion<typename TList::Head, T>::sameType };
|
typedef typename TList::Tail Tail;
|
||||||
typedef typename Select<!TList_is_null & Head_is_T, Typelist<U, typename ReplaceAll<typename TList::Tail, T, U>::Result>, NullType>::Result Result1;
|
|
||||||
public:
|
private:
|
||||||
typedef typename Select<!TList_is_null & !Head_is_T, Typelist<typename TList::Head, typename ReplaceAll<typename TList::Tail, T, U>::Result>, Result1>::Result Result;
|
ASSERT_TYPELIST(TList);
|
||||||
};
|
|
||||||
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
typedef typename ReplaceAll<Tail, T, U>::Result TailResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
SameType<Head, T>::value,
|
||||||
|
Typelist<U, TailResult>,
|
||||||
|
Typelist<Head, TailResult>
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Reverse
|
// class template Reverse
|
||||||
// Reverses a typelist
|
// Reverses a typelist
|
||||||
|
@ -716,18 +905,28 @@ public:
|
||||||
// returns a typelist that is TList reversed
|
// returns a typelist that is TList reversed
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList>
|
template <class TList> struct Reverse;
|
||||||
struct Reverse {
|
|
||||||
private:
|
template <>
|
||||||
enum { list_of_one = Conversion<typename TList::Tail, NullType>::sameType };
|
struct Reverse<NullType>
|
||||||
public:
|
{
|
||||||
typedef typename Select<list_of_one,
|
typedef NullType Result;
|
||||||
TList,
|
};
|
||||||
typename Append<typename Reverse<typename TList::Tail>::Result,
|
|
||||||
typename TList::Head
|
template <class TList>
|
||||||
>::Result
|
struct Reverse
|
||||||
>::Result Result;
|
{
|
||||||
};
|
private:
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Append<
|
||||||
|
typename Reverse<Tail>::Result, Head>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template MostDerived
|
// class template MostDerived
|
||||||
|
@ -737,18 +936,41 @@ public:
|
||||||
// returns the type in TList that's the most derived from T
|
// returns the type in TList that's the most derived from T
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class TList, class T>
|
template <class TList, class T>
|
||||||
struct MostDerived {
|
struct MostDerived
|
||||||
private:
|
{
|
||||||
enum { TList_is_null = Conversion<TList, NullType>::sameType };
|
typedef typename TList::Head Head;
|
||||||
typedef typename Select<TList_is_null, T, typename MostDerived<typename TList::Tail, T>::Result>::Result Candidate;
|
typedef typename TList::Tail Tail;
|
||||||
public:
|
|
||||||
typedef typename Select<TList_is_null, T,
|
private:
|
||||||
typename Select<SUPERSUBCLASS(Candidate, typename TList::Head),
|
ASSERT_TYPELIST(TList);
|
||||||
typename TList::Head, Candidate
|
|
||||||
>::Result
|
template<class TList1>
|
||||||
>::Result Result;
|
struct In
|
||||||
};
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList1::Tail Tail;
|
||||||
|
typedef typename TList1::Head Head;
|
||||||
|
typedef typename MostDerived<Tail, T>::Result Candidate;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
SUPERSUBCLASS(Candidate, Head),
|
||||||
|
Head, Candidate
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In<NullType>
|
||||||
|
{
|
||||||
|
typedef T Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template DerivedToFront
|
// class template DerivedToFront
|
||||||
|
@ -757,41 +979,68 @@ public:
|
||||||
// DerivedToFront<TList>::Result
|
// DerivedToFront<TList>::Result
|
||||||
// returns the reordered TList
|
// returns the reordered TList
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace DerivedToFront_ {
|
|
||||||
|
|
||||||
template<class TList>
|
|
||||||
struct ListType {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct ListType<NullType> {
|
|
||||||
typedef NullType Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace DerivedToFront_
|
|
||||||
|
|
||||||
template<class TList>
|
|
||||||
struct DerivedToFront;
|
|
||||||
|
|
||||||
template<>
|
template <class TList> struct DerivedToFront;
|
||||||
struct DerivedToFront<NullType> {
|
|
||||||
typedef NullType Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class TList>
|
template <>
|
||||||
struct DerivedToFront {
|
struct DerivedToFront<NullType>
|
||||||
private:
|
{
|
||||||
typedef typename MostDerived<typename TList::Tail,
|
typedef NullType Result;
|
||||||
typename TList::Head>::Result TheMostDerived;
|
};
|
||||||
typedef typename Replace<typename TList::Tail, TheMostDerived,
|
|
||||||
typename TList::Head>::Result L;
|
|
||||||
public:
|
|
||||||
typedef Typelist<TheMostDerived, L> Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TL
|
template <class TList>
|
||||||
|
struct DerivedToFront
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
|
||||||
|
typedef typename ReplaceAll<Tail, TheMostDerived, Head>::Result Temp;
|
||||||
|
typedef typename DerivedToFront<Temp>::Result L;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Typelist<TheMostDerived, L> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template DerivedToFrontAll
|
||||||
|
// Arranges all the types in a typelist so that the most derived types appear first
|
||||||
|
// Invocation (TList is a typelist):
|
||||||
|
// DerivedToFront<TList>::Result
|
||||||
|
// returns the reordered TList
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList> struct DerivedToFrontAll;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct DerivedToFrontAll<NullType>
|
||||||
|
{
|
||||||
|
typedef NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct DerivedToFrontAll
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
|
||||||
|
typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
|
||||||
|
|
||||||
|
typedef typename DerivedToFrontAll<L>::Result TailResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Typelist<TheMostDerived, TailResult> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace TL
|
||||||
} // namespace Loki
|
} // namespace Loki
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -799,7 +1048,7 @@ public:
|
||||||
// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27
|
// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27
|
||||||
// (credit due to Dave Taylor)
|
// (credit due to Dave Taylor)
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
// August 22, 2001: ported by Jonathan H Lundquist to MSVC
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // TYPELIST_INC_
|
#endif // TYPELIST_INC_
|
||||||
|
|
|
@ -13,24 +13,13 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: August 22, 2001
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
#ifndef TYPEMANIP_INC_
|
#ifndef TYPEMANIP_INC_
|
||||||
#define TYPEMANIP_INC_
|
#define TYPEMANIP_INC_
|
||||||
|
|
||||||
namespace Loki {
|
namespace Loki
|
||||||
|
{
|
||||||
namespace Private {
|
|
||||||
|
|
||||||
struct big { char c[2]; };
|
|
||||||
|
|
||||||
struct any {
|
|
||||||
template<typename T>
|
|
||||||
any(const T&);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Private
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Int2Type
|
// class template Int2Type
|
||||||
// Converts each integral constant into a unique type
|
// Converts each integral constant into a unique type
|
||||||
|
@ -53,8 +42,9 @@ namespace Loki {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Type2Type
|
struct Type2Type
|
||||||
{
|
{
|
||||||
typedef T OriginalType;
|
typedef T OriginalType;
|
||||||
|
Type2Type(){} // VC7
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -67,96 +57,98 @@ namespace Loki {
|
||||||
// Result evaluates to T if flag is true, and to U otherwise.
|
// Result evaluates to T if flag is true, and to U otherwise.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Private {
|
template <bool flag, typename T, typename U>
|
||||||
|
struct Select
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<bool>
|
||||||
|
struct In
|
||||||
|
{ typedef T Result; };
|
||||||
|
|
||||||
namespace Select_ {
|
template<>
|
||||||
|
struct In<false>
|
||||||
|
{ typedef U Result; };
|
||||||
|
|
||||||
struct ChooseT {
|
public:
|
||||||
template<typename T, typename U>
|
typedef typename In<flag>::Result Result;
|
||||||
struct Choose {
|
};
|
||||||
typedef T Result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ChooseU {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename T, typename U>
|
// class template SameType
|
||||||
struct Choose {
|
// Return true iff two given types are the same
|
||||||
typedef U Result;
|
// Invocation: SameType<T, U>::value
|
||||||
};
|
// where:
|
||||||
};
|
// T and U are types
|
||||||
|
// Result evaluates to true iff U == T (types equal)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<bool flag>
|
template <typename T, typename U>
|
||||||
struct Selector {
|
struct SameType
|
||||||
typedef ChooseT Result;
|
{
|
||||||
};
|
private:
|
||||||
|
template<typename>
|
||||||
|
struct In
|
||||||
|
{ enum { value = false }; };
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Selector<false> {
|
struct In<T>
|
||||||
typedef ChooseU Result;
|
{ enum { value = true }; };
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Select_
|
public:
|
||||||
|
enum { value = In<U>::value };
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
} // namespace Private
|
namespace Private
|
||||||
|
{
|
||||||
|
typedef char Small;
|
||||||
|
class Big { char dummy[2]; };
|
||||||
|
|
||||||
template<bool flag, typename T, typename U>
|
template<typename T>
|
||||||
struct Select {
|
struct IsVoid
|
||||||
private:
|
{
|
||||||
typedef typename Private::Select_::Selector<flag>::Result selector;
|
enum { result =
|
||||||
public:
|
SameType<T, void>::value ||
|
||||||
typedef typename selector::Choose<T, U>::Result Result;
|
SameType<T, const void>::value ||
|
||||||
};
|
SameType<T, volatile void>::value ||
|
||||||
|
SameType<T, const volatile void>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace Private {
|
//
|
||||||
|
// is one type convertable to another?
|
||||||
|
//
|
||||||
|
template <class T, class U>
|
||||||
|
class is_convertible
|
||||||
|
{
|
||||||
|
struct VoidReplace {};
|
||||||
|
|
||||||
template<typename T>
|
typedef typename Select
|
||||||
struct is_void {
|
<
|
||||||
enum { value = 0 };
|
Private::IsVoid<T>::result,
|
||||||
};
|
VoidReplace, T
|
||||||
|
>
|
||||||
|
::Result T1;
|
||||||
|
|
||||||
template<>
|
typedef typename Select
|
||||||
struct is_void<void> {
|
<
|
||||||
enum { value = 1 };
|
Private::IsVoid<U>::result,
|
||||||
};
|
VoidReplace, U
|
||||||
|
>
|
||||||
|
::Result U1;
|
||||||
|
|
||||||
namespace is_same_ {
|
static Private::Big Test(...);
|
||||||
|
static Private::Small Test(U1);
|
||||||
|
static T1 MakeT();
|
||||||
|
|
||||||
template<typename T>
|
public:
|
||||||
char test_same(T*, T*);
|
enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
|
||||||
|
};
|
||||||
template<typename T>
|
|
||||||
big test_same(T*, any);
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct is_same_imp {
|
|
||||||
static T t;
|
|
||||||
static U u;
|
|
||||||
enum { result = sizeof(test_same(&t, &u)) == sizeof(char) };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace is_same_
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct is_same {
|
|
||||||
enum { voidT = is_void<T>::value };
|
|
||||||
enum { voidU = is_void<U>::value };
|
|
||||||
struct BothVoid {
|
|
||||||
enum { result = 1 };
|
|
||||||
};
|
|
||||||
struct OneVoid {
|
|
||||||
enum { result = 0 };
|
|
||||||
};
|
|
||||||
typedef typename Select<voidT & voidU,
|
|
||||||
BothVoid,
|
|
||||||
typename Select<voidT | voidU,
|
|
||||||
OneVoid,
|
|
||||||
is_same_::is_same_imp<T, U>
|
|
||||||
>::Result
|
|
||||||
>::Result tester;
|
|
||||||
enum { result = tester::result };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Private
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Conversion
|
// class template Conversion
|
||||||
|
@ -174,65 +166,13 @@ struct is_same {
|
||||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Private {
|
template <class T, class U>
|
||||||
|
struct Conversion
|
||||||
namespace Conversion_ {
|
{
|
||||||
|
enum { exists = (is_convertible<T,U>::exists) };
|
||||||
#ifdef _MSC_VER
|
enum { exists2Way = (exists && is_convertible<U, T>::exists) };
|
||||||
#pragma warning(push)
|
enum { sameType = (SameType<T, U>::value) };
|
||||||
#pragma warning(disable:4181)
|
};
|
||||||
#pragma warning(disable:4800)
|
|
||||||
#pragma warning(disable:4244)
|
|
||||||
#endif
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct Determine {
|
|
||||||
template<typename X, typename Y>
|
|
||||||
struct tester {
|
|
||||||
static char test(X, Y);
|
|
||||||
static big test(any, any);
|
|
||||||
};
|
|
||||||
static T t;
|
|
||||||
static U u;
|
|
||||||
enum { exists = sizeof(tester<T, U>::test(t, t)) == sizeof(char) };
|
|
||||||
enum { exists2Way = exists & (sizeof(tester<U, T>::test(u, u)) == sizeof(char)) };
|
|
||||||
enum { sameType = exists2Way & is_same<T, U>::result };
|
|
||||||
};
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Conversion_
|
|
||||||
|
|
||||||
} // namespace Private
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct Conversion {
|
|
||||||
private:
|
|
||||||
enum { voidT = Private::is_void<T>::value };
|
|
||||||
enum { voidU = Private::is_void<U>::value };
|
|
||||||
|
|
||||||
struct both_void {
|
|
||||||
enum { exists = 1, exists2Way = 1, sameType = 1 };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct one_void {
|
|
||||||
enum { exists = 1, exists2Way = 0, sameType = 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef typename Select<voidT & voidU,
|
|
||||||
both_void,
|
|
||||||
typename Select<voidT | voidU,
|
|
||||||
one_void,
|
|
||||||
Private::Conversion_::Determine<T, U>
|
|
||||||
>::Result
|
|
||||||
>::Result Chooser;
|
|
||||||
public:
|
|
||||||
enum { exists = Chooser::exists };
|
|
||||||
enum { exists2Way = Chooser::exists2Way };
|
|
||||||
enum { sameType = Chooser::sameType };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Loki
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// macro SUPERSUBCLASS
|
// macro SUPERSUBCLASS
|
||||||
|
@ -244,8 +184,8 @@ public:
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define SUPERSUBCLASS(T, U) \
|
#define SUPERSUBCLASS(T, U) \
|
||||||
(::Loki::Conversion<const U*, const T*>::exists && \
|
(::Loki::Conversion<const volatile U*, const volatile T*>::exists && \
|
||||||
!::Loki::Conversion<const T*, const void*>::sameType)
|
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// macro SUPERSUBCLASS
|
// macro SUPERSUBCLASS
|
||||||
|
@ -257,12 +197,15 @@ public:
|
||||||
|
|
||||||
#define SUPERSUBCLASS_STRICT(T, U) \
|
#define SUPERSUBCLASS_STRICT(T, U) \
|
||||||
(SUPERSUBCLASS(T, U) && \
|
(SUPERSUBCLASS(T, U) && \
|
||||||
!::Loki::Conversion<const T, const U>::sameType)
|
!::Loki::Conversion<const volatile T *, const volatile U *>::sameType)
|
||||||
|
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
// August 22, 2001: ported by Jonathan H Lundquist to MSVC6
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // TYPEMANIP_INC_
|
#endif // TYPEMANIP_INC_
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
#ifndef TYPETRAITS_INC_
|
#ifndef TYPETRAITS_INC_
|
||||||
#define TYPETRAITS_INC_
|
#define TYPETRAITS_INC_
|
||||||
|
|
||||||
|
@ -21,14 +38,7 @@ namespace Loki
|
||||||
struct IsCustomUnsignedInt
|
struct IsCustomUnsignedInt
|
||||||
{
|
{
|
||||||
enum { value = 0 };
|
enum { value = 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
template<>
|
|
||||||
struct IsCustomUnsignedInt<unsigned __int64> {
|
|
||||||
enum { value = 1 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template IsCustomSignedInt
|
// class template IsCustomSignedInt
|
||||||
|
@ -48,13 +58,6 @@ namespace Loki
|
||||||
enum { value = 0 };
|
enum { value = 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
template<>
|
|
||||||
struct IsCustomSignedInt<__int64> {
|
|
||||||
enum { value = 1 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template IsCustomFloat
|
// class template IsCustomFloat
|
||||||
// Offers a means to integrate nonstandard floating point types with the
|
// Offers a means to integrate nonstandard floating point types with the
|
||||||
|
@ -84,189 +87,6 @@ namespace Loki
|
||||||
int, long int) StdSignedInts;
|
int, long int) StdSignedInts;
|
||||||
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
|
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
|
||||||
typedef TYPELIST_3(float, double, long double) StdFloats;
|
typedef TYPELIST_3(float, double, long double) StdFloats;
|
||||||
|
|
||||||
char test_ptr(const volatile void*, const volatile void*);
|
|
||||||
big test_ptr(any, any);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T* unrefptr(T&);
|
|
||||||
|
|
||||||
char test_const(const volatile void*);
|
|
||||||
big test_const(volatile void*);
|
|
||||||
char test_volatile(const volatile void*);
|
|
||||||
big test_volatile(const void*);
|
|
||||||
|
|
||||||
template<typename V, typename X>
|
|
||||||
char test_mptr(V X::*, any);
|
|
||||||
|
|
||||||
big test_mptr(any, any);
|
|
||||||
|
|
||||||
template<bool isReference>
|
|
||||||
struct AddReferenceImp {
|
|
||||||
template<typename T>
|
|
||||||
struct Imp {
|
|
||||||
typedef T Result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct AddReferenceImp<false> {
|
|
||||||
template<typename T>
|
|
||||||
struct Imp {
|
|
||||||
typedef T& Result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
template <class U> struct PointerTraits
|
|
||||||
{
|
|
||||||
enum { result = false };
|
|
||||||
typedef NullType PointeeType;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U> struct PointerTraits<U*>
|
|
||||||
{
|
|
||||||
enum { result = true };
|
|
||||||
typedef U PointeeType;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
template<typename U>
|
|
||||||
struct PointerTraits {
|
|
||||||
private:
|
|
||||||
static U u;
|
|
||||||
public:
|
|
||||||
typedef void PointeeType; // unable to determine correctly
|
|
||||||
enum { result = sizeof(Private::test_ptr(&u, u)) == sizeof(char) };
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct PointerTraits<void> {
|
|
||||||
typedef void PointeeType;
|
|
||||||
enum { result = 0 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
template <class U> struct ReferenceTraits
|
|
||||||
{
|
|
||||||
enum { result = false };
|
|
||||||
typedef U ReferredType;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U> struct ReferenceTraits<U&>
|
|
||||||
{
|
|
||||||
enum { result = true };
|
|
||||||
typedef U ReferredType;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable:4181)
|
|
||||||
template<typename U>
|
|
||||||
struct ReferenceTraits {
|
|
||||||
typedef U const volatile cv_u;
|
|
||||||
static cv_u u;
|
|
||||||
public:
|
|
||||||
enum { result = (sizeof(Private::test_const(&u)) != sizeof(char))
|
|
||||||
| (sizeof(Private::test_volatile(&u)) != sizeof(char)) };
|
|
||||||
typedef void ReferredType; // unable to determine correctly
|
|
||||||
};
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct ReferenceTraits<void> {
|
|
||||||
enum { result = 0 };
|
|
||||||
typedef void ReferredType;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
template <class U> struct PToMTraits
|
|
||||||
{
|
|
||||||
enum { result = false };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U, class V>
|
|
||||||
struct PToMTraits<U V::*>
|
|
||||||
{
|
|
||||||
enum { result = true };
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
template<typename U>
|
|
||||||
struct PToMTraits {
|
|
||||||
private:
|
|
||||||
static U u;
|
|
||||||
public:
|
|
||||||
enum { result = sizeof(Private::test_mptr(u, &u)) == sizeof(char) };
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct PToMTraits<void> {
|
|
||||||
enum { result = 0 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
template <class U> struct UnConst
|
|
||||||
{
|
|
||||||
typedef U Result;
|
|
||||||
enum { isConst = 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U> struct UnConst<const U>
|
|
||||||
{
|
|
||||||
typedef U Result;
|
|
||||||
enum { isConst = 1 };
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
template<typename U>
|
|
||||||
struct UnConst {
|
|
||||||
private:
|
|
||||||
static U u;
|
|
||||||
public:
|
|
||||||
typedef void Result; // unable to determine correctly
|
|
||||||
enum { isConst = sizeof(Private::test_const(Private::unrefptr(u))) == sizeof(char) };
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct UnConst<void> {
|
|
||||||
typedef void Result;
|
|
||||||
enum { isConst = 0 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
template <class U> struct UnVolatile
|
|
||||||
{
|
|
||||||
typedef U Result;
|
|
||||||
enum { isVolatile = 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U> struct UnVolatile<volatile U>
|
|
||||||
{
|
|
||||||
typedef U Result;
|
|
||||||
enum { isVolatile = 1 };
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
template<typename U>
|
|
||||||
struct UnVolatile {
|
|
||||||
private:
|
|
||||||
static U u;
|
|
||||||
public:
|
|
||||||
typedef void Result; // unable to determine correctly
|
|
||||||
enum { isVolatile = sizeof(Private::test_volatile(Private::unrefptr(u))) == sizeof(char) };
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct UnVolatile<void> {
|
|
||||||
typedef void Result;
|
|
||||||
enum { isVolatile = 0 };
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
template<typename U, bool isReference>
|
|
||||||
struct AddReference {
|
|
||||||
typedef typename Private::AddReferenceImp<isReference>::template Imp<U>::Result Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct AddReference<void, false> {
|
|
||||||
typedef void Result;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -325,50 +145,203 @@ namespace Loki
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypeTraits
|
class TypeTraits
|
||||||
{
|
{
|
||||||
public:
|
typedef char (&yes)[1];
|
||||||
static const isPointer = Private::PointerTraits<T>::result;
|
typedef char (&no) [2];
|
||||||
//enum { isPointer = Private::PointerTraits<T>::result };
|
|
||||||
typedef typename Private::PointerTraits<T>::PointeeType PointeeType;
|
template<typename U, size_t N>
|
||||||
static const isReference = Private::ReferenceTraits<T>::result;
|
static void vc7_need_this_for_is_array(Type2Type<U[N]>);
|
||||||
typedef typename Private::ReferenceTraits<T>::ReferredType ReferredType;
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_reference(Type2Type<U&>);
|
||||||
|
static no is_reference(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_pointer1(Type2Type<U*>);
|
||||||
|
static no is_pointer1(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_pointer2(Type2Type<U const *>);
|
||||||
|
static no is_pointer2(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_pointer3(Type2Type<U volatile *>);
|
||||||
|
static no is_pointer3(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_pointer4(Type2Type<U const volatile *>);
|
||||||
|
static no is_pointer4(...);
|
||||||
|
|
||||||
|
template<typename U, typename V>
|
||||||
|
static yes is_pointer2member(Type2Type<U V::*>);
|
||||||
|
static no is_pointer2member(...);
|
||||||
|
|
||||||
|
template<typename U, size_t N>
|
||||||
|
static yes is_array1(Type2Type<U[N]>);
|
||||||
|
static no is_array1(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_array2(Type2Type<U[]>);
|
||||||
|
static no is_array2(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_const(Type2Type<const U>);
|
||||||
|
static no is_const(...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
static yes is_volatile(Type2Type<volatile U>);
|
||||||
|
static no is_volatile(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//
|
||||||
|
// VC7 BUG - will not detect refernce to function
|
||||||
|
//
|
||||||
|
enum {
|
||||||
|
isReference =
|
||||||
|
sizeof(is_reference(Type2Type<T>())) == sizeof(yes)
|
||||||
|
};
|
||||||
|
|
||||||
static const isMemberPointer = Private::PToMTraits<T>::result;
|
//
|
||||||
|
// VC7 BUG - will not detect pointer to function
|
||||||
|
//
|
||||||
|
enum {
|
||||||
|
isPointer =
|
||||||
|
sizeof(is_pointer1(Type2Type<T>())) == sizeof(yes) ||
|
||||||
|
sizeof(is_pointer2(Type2Type<T>())) == sizeof(yes) ||
|
||||||
|
sizeof(is_pointer3(Type2Type<T>())) == sizeof(yes) ||
|
||||||
|
sizeof(is_pointer4(Type2Type<T>())) == sizeof(yes)
|
||||||
|
};
|
||||||
|
|
||||||
static const isStdUnsignedInt =
|
enum {
|
||||||
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0;
|
isMemberPointer =
|
||||||
static const isStdSignedInt =
|
sizeof(is_pointer2member(Type2Type<T>())) == sizeof(yes)
|
||||||
TL::IndexOf<Private::StdSignedInts, T>::value >= 0;
|
};
|
||||||
static const isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
|
|
||||||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0;
|
enum {
|
||||||
static const isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0;
|
isArray =
|
||||||
static const isStdArith = isStdIntegral || isStdFloat;
|
sizeof(is_array1(Type2Type<T>())) == sizeof(yes) ||
|
||||||
static const isStdFundamental = isStdArith || isStdFloat ||
|
sizeof(is_array2(Type2Type<T>())) == sizeof(yes)
|
||||||
Conversion<T, void>::sameType;
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
isVoid =
|
||||||
|
SameType<T, void>::value ||
|
||||||
|
SameType<T, const void>::value ||
|
||||||
|
SameType<T, volatile void>::value ||
|
||||||
|
SameType<T, const volatile void>::value
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { isStdUnsignedInt =
|
||||||
|
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0 };
|
||||||
|
enum { isStdSignedInt =
|
||||||
|
TL::IndexOf<Private::StdSignedInts, T>::value >= 0 };
|
||||||
|
enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
|
||||||
|
TL::IndexOf<Private::StdOtherInts, T>::value >= 0 };
|
||||||
|
enum { isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0 };
|
||||||
|
enum { isStdArith = isStdIntegral || isStdFloat };
|
||||||
|
enum { isStdFundamental = isStdArith || isStdFloat || isVoid };
|
||||||
|
|
||||||
static const isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value;
|
enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
|
||||||
static const isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value;
|
enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
|
||||||
static const isIntegral = isStdIntegral || isUnsignedInt || isSignedInt;
|
enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
|
||||||
static const isFloat = isStdFloat || IsCustomFloat<T>::value;
|
enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
|
||||||
static const isArith = isIntegral || isFloat;
|
enum { isArith = isIntegral || isFloat };
|
||||||
static const isFundamental = isStdFundamental || isArith || isFloat;
|
enum { isFundamental = isStdFundamental || isArith || isFloat };
|
||||||
|
|
||||||
typedef typename Select<isStdArith || isPointer || isMemberPointer, T,
|
enum {
|
||||||
typename Private::AddReference<T, isReference>::Result
|
isConst =
|
||||||
>::Result ParameterType;
|
sizeof(is_const(Type2Type<T>())) == sizeof(yes)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
isVolatile =
|
||||||
|
sizeof(is_volatile(Type2Type<T>())) == sizeof(yes)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static const isConst = Private::UnConst<T>::isConst;
|
private:
|
||||||
typedef typename Private::UnConst<T>::Result NonConstType;
|
// is_scalar include functions types
|
||||||
static const isVolatile = Private::UnVolatile<T>::isVolatile;
|
struct is_scalar
|
||||||
typedef typename Private::UnVolatile<T>::Result NonVolatileType;
|
{
|
||||||
typedef typename Private::UnVolatile<typename Private::UnConst<T>::Result>::Result
|
private:
|
||||||
UnqualifiedType;
|
struct BoolConvert { BoolConvert(bool); };
|
||||||
|
|
||||||
|
static yes check(BoolConvert);
|
||||||
|
static no check(...);
|
||||||
|
|
||||||
|
struct NotScalar {};
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isVoid || isReference || isArray,
|
||||||
|
NotScalar, T
|
||||||
|
>
|
||||||
|
::Result RetType;
|
||||||
|
|
||||||
|
static RetType& get();
|
||||||
|
|
||||||
|
public:
|
||||||
|
//
|
||||||
|
// Ignore forcing value to bool 'true' or 'false' (performance warning)
|
||||||
|
//
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable: 4800)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { value = sizeof(check(get())) == sizeof(yes) };
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (default: 4800)
|
||||||
|
#endif
|
||||||
|
}; // is_scalar
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<bool IsRef>
|
||||||
|
struct AdjReference
|
||||||
|
{
|
||||||
|
template<typename U>
|
||||||
|
struct In { typedef U const & Result; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AdjReference<true>
|
||||||
|
{
|
||||||
|
template<typename U>
|
||||||
|
struct In { typedef U Result; };
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef typename AdjReference<isReference || isVoid>::
|
||||||
|
template In<T>::Result AdjType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum { isScalar = is_scalar::value };
|
||||||
|
|
||||||
|
|
||||||
|
typedef typename Select
|
||||||
|
<
|
||||||
|
isScalar || isArray, T, AdjType
|
||||||
|
>
|
||||||
|
::Result ParameterType;
|
||||||
|
|
||||||
|
//
|
||||||
|
// We get is_class for free
|
||||||
|
// BUG - fails with functions types (ICE) and unknown size array
|
||||||
|
// (but works for other incomplete types)
|
||||||
|
// (the boost one (Paul Mensonides) is better)
|
||||||
|
//
|
||||||
|
enum { isClass =
|
||||||
|
!isScalar &&
|
||||||
|
!isArray &&
|
||||||
|
!isReference &&
|
||||||
|
!isVoid
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
// August 22, 2001: ported by Jonathan H Lundquist to MSVC
|
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // TYPETRAITS_INC_
|
#endif // TYPETRAITS_INC_
|
||||||
|
|
106
MSVC/1300/VC_Alignment.h
Normal file
106
MSVC/1300/VC_Alignment.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Last update: June 20, 2001
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma once
|
||||||
|
#else
|
||||||
|
# error "Visual C++ specific header !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VC_ALIGNMENT_INC_
|
||||||
|
#define VC_ALIGNMENT_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "static_check.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template MaxAlign
|
||||||
|
// Computes the maximum alignof for all types in a typelist
|
||||||
|
// Usage: MaxAlign<TList>::result
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList> struct VC_MaxAlign;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VC_MaxAlign< ::Loki::NullType >
|
||||||
|
{
|
||||||
|
enum { result = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct VC_MaxAlign
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { headResult = __alignof(Head) };
|
||||||
|
enum { tailResult = VC_MaxAlign<Tail>::result };
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum { result = headResult > tailResult ?
|
||||||
|
headResult : tailResult };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class VC_AlignedPODBase
|
||||||
|
// Defines a host of protected types used by VC_AlignedPOD (defined later)
|
||||||
|
// Could be just part of VC_AlignedPOD itself, but making it separate ought to
|
||||||
|
// reduce compile times
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class VC_AlignedPODBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
template<unsigned AlignmentSize>
|
||||||
|
struct AlignedPod
|
||||||
|
{
|
||||||
|
STATIC_CHECK(AlignmentSize == 0, BadAlignmentSize_OnlyUpTo128);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// I used the macro because align(#)
|
||||||
|
// only works with Integer literals
|
||||||
|
//
|
||||||
|
#define ALIGNED_POD(_size_) \
|
||||||
|
template<> struct AlignedPod<_size_> { \
|
||||||
|
__declspec(align(_size_)) struct type { char X[_size_]; }; \
|
||||||
|
enum { alignment = __alignof(type) }; }; \
|
||||||
|
STATIC_CHECK((_size_ == sizeof(AlignedPod<_size_>::type)), SizeofNotEqualSize); \
|
||||||
|
STATIC_CHECK((_size_ == (AlignedPod<_size_>::alignment)), SizeofNotEqualAlignof)
|
||||||
|
|
||||||
|
|
||||||
|
ALIGNED_POD(1);
|
||||||
|
ALIGNED_POD(2);
|
||||||
|
ALIGNED_POD(4);
|
||||||
|
ALIGNED_POD(8);
|
||||||
|
ALIGNED_POD(16);
|
||||||
|
ALIGNED_POD(32);
|
||||||
|
ALIGNED_POD(64);
|
||||||
|
ALIGNED_POD(128);
|
||||||
|
// can be up to 8192 - is it realistic?
|
||||||
|
|
||||||
|
#undef ALIGNED_POD
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template VC_AlignedPOD
|
||||||
|
// Computes the alignment of all types in a typelist
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename TList>
|
||||||
|
class VC_AlignedPOD : VC_AlignedPODBase
|
||||||
|
{
|
||||||
|
enum { maxAlign = VC_MaxAlign<TList>::result };
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename AlignedPod<maxAlign>::type Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VC_ALIGNMENT_INC_
|
||||||
|
|
864
MSVC/1300/Variant.h
Normal file
864
MSVC/1300/Variant.h
Normal file
|
@ -0,0 +1,864 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2001, 2002 by Andrei Alexandrescu
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author makes no representations about the suitability of this software
|
||||||
|
// for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef VARIANT_INC_
|
||||||
|
#define VARIANT_INC_
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include "Visitor.h"
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "static_check.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// At the moment there is no namespace for Variant
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include "VC_Alignment.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template ConfigurableUnion
|
||||||
|
// Builds a union that contains each type in a typelist
|
||||||
|
// Usage: ConfigurableUnion<TList> is the very type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class U> union ConfigurableUnion;
|
||||||
|
|
||||||
|
template <> union ConfigurableUnion< ::Loki::NullType >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
union ConfigurableUnion
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Head head_;
|
||||||
|
ConfigurableUnion<Tail> tail_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template MaxSize
|
||||||
|
// Computes the maximum sizeof for all types in a typelist
|
||||||
|
// Usage: MaxSize<TList>::result
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList> struct MaxSize;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MaxSize< ::Loki::NullType >
|
||||||
|
{
|
||||||
|
enum { result = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct MaxSize
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { headResult = sizeof(Head) };
|
||||||
|
enum { tailResult = MaxSize<Tail>::result };
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum { result = headResult > tailResult ?
|
||||||
|
headResult : tailResult };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class AlignedPODBase
|
||||||
|
// Defines a host of protected types used by AlignedPOD (defined later)
|
||||||
|
// Could be just part of AlignedPOD itself, but making it separate ought to
|
||||||
|
// reduce compile times
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class AlignedPODBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
template <class TList, std::size_t size>
|
||||||
|
struct ComputeAlignBound
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class TList1>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TList1::Head Head1;
|
||||||
|
typedef typename TList1::Tail Tail1;
|
||||||
|
|
||||||
|
typedef typename ComputeAlignBound<Tail1, size>::Result TailResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename ::Loki::Select
|
||||||
|
<
|
||||||
|
sizeof(Head1) <= size,
|
||||||
|
::Loki::Typelist<Head1, TailResult>,
|
||||||
|
TailResult
|
||||||
|
>
|
||||||
|
::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In< ::Loki::NullType >
|
||||||
|
{
|
||||||
|
typedef ::Loki::NullType Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In<TList>::Result Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U> struct Structify
|
||||||
|
{ U dummy_; };
|
||||||
|
|
||||||
|
class Unknown;
|
||||||
|
|
||||||
|
// VC7: fatal error C1067: compiler limit :
|
||||||
|
// debug information module size exceeded
|
||||||
|
// Therfore I decreased the list to 26 without
|
||||||
|
// changing the rage of detectable alignment
|
||||||
|
typedef TYPELIST_26(
|
||||||
|
char,
|
||||||
|
wchar_t,
|
||||||
|
short int,
|
||||||
|
int,
|
||||||
|
long int,
|
||||||
|
float,
|
||||||
|
double,
|
||||||
|
long double,
|
||||||
|
char*,
|
||||||
|
void*,
|
||||||
|
Unknown (*)(Unknown),
|
||||||
|
Unknown* Unknown::*,
|
||||||
|
Unknown (Unknown::*)(Unknown),
|
||||||
|
Structify<char>,
|
||||||
|
Structify<wchar_t>,
|
||||||
|
Structify<short int>,
|
||||||
|
Structify<int>,
|
||||||
|
Structify<long int>,
|
||||||
|
Structify<float>,
|
||||||
|
Structify<double>,
|
||||||
|
Structify<long double>,
|
||||||
|
Structify<char*>,
|
||||||
|
Structify<void*>,
|
||||||
|
Structify<Unknown (*)(Unknown)>,
|
||||||
|
Structify<Unknown* Unknown::*>,
|
||||||
|
Structify<Unknown (Unknown::*)(Unknown)>
|
||||||
|
)
|
||||||
|
TypesOfAllAlignments;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template AlignedPOD
|
||||||
|
// Computes the alignment of all types in a typelist
|
||||||
|
// Usage: ConfigurableUnion<TList> is the very type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename TList>
|
||||||
|
class AlignedPOD : private AlignedPODBase
|
||||||
|
{
|
||||||
|
enum { maxSize = MaxSize<TList>::result };
|
||||||
|
|
||||||
|
typedef typename ComputeAlignBound
|
||||||
|
<
|
||||||
|
TypesOfAllAlignments,
|
||||||
|
maxSize
|
||||||
|
>
|
||||||
|
::Result AlignTypes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef ConfigurableUnion<AlignTypes> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template MakeConst
|
||||||
|
// Given a typelist TList, returns a typelist that contains the types in TList
|
||||||
|
// adding a const qualifier to each.
|
||||||
|
// Usage: MakeConst<TList>::Result
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList> struct MakeConst;
|
||||||
|
|
||||||
|
template <> struct MakeConst< ::Loki::NullType >
|
||||||
|
{
|
||||||
|
typedef ::Loki::NullType Result; // terminator is not const
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct MakeConst
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Head;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename MakeConst<Tail>::Result NewTail;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef ::Loki::Typelist<const Head, NewTail> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Converter
|
||||||
|
// Supports the Variant-to-Variant conversion constructor
|
||||||
|
// Guaranteed to issue an internal compiler error on:
|
||||||
|
// 1. Metrowerks CodeWarrior 7.0 (internal compiler error: File:
|
||||||
|
// 'CTemplateTools.c' Line: 1477
|
||||||
|
// Variant.h line 244 UnitBase > VisitorBase;)
|
||||||
|
// 2. Microsoft Visual C++ 7.1 alpha release (Assertion failed:
|
||||||
|
// ( name - nameBuf ) < LIMIT_ID_LENGTH,
|
||||||
|
// file f:\vs70builds\2108\vc\Compiler\CxxFE\sl\P1\C\outdname.c,
|
||||||
|
// line 4583)
|
||||||
|
// 3. GNU gcc 2.95.3-6 (Internal compiler error 980422)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class VariantFrom, class VariantTo>
|
||||||
|
struct Converter
|
||||||
|
{
|
||||||
|
//private: VC7 complains
|
||||||
|
struct UnitBase : public VariantFrom::ConstStrictVisitor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
VariantTo* storageForDestination;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Type, class Base>
|
||||||
|
struct Unit : public Base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||||
|
{
|
||||||
|
new(this->storageForDestination) VariantTo(obj);
|
||||||
|
}
|
||||||
|
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot convert");
|
||||||
|
}
|
||||||
|
virtual void Visit(const Type& obj)
|
||||||
|
{
|
||||||
|
using namespace Loki;
|
||||||
|
typedef typename VariantTo::Types TList;
|
||||||
|
enum { dispatch = TL::IndexOf<TList, Type>::value > -1 };
|
||||||
|
this->DoVisit(obj, Int2Type<dispatch>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef ::Loki::GenLinearHierarchy
|
||||||
|
<
|
||||||
|
typename VariantFrom::Types,
|
||||||
|
Unit,
|
||||||
|
UnitBase
|
||||||
|
>
|
||||||
|
VisitorBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Visitor : public VisitorBase
|
||||||
|
{
|
||||||
|
explicit Visitor(VariantTo& dest)
|
||||||
|
{
|
||||||
|
// Initialize the pointer to destination
|
||||||
|
this->storageForDestination = &dest;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template ConverterTo
|
||||||
|
// Supports Variant-to-T conversion
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#if 0
|
||||||
|
template <class VariantFrom, class T>
|
||||||
|
struct ConverterTo
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct DestHolder
|
||||||
|
: VariantFrom::ConstStrictVisitor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
DestHolder() {}
|
||||||
|
DestHolder(const T& dest) : destination_(dest) {}
|
||||||
|
T destination_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList>
|
||||||
|
struct VisitorBase
|
||||||
|
: VisitorBase<typename TList::Tail>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
typedef typename TList::Head Type;
|
||||||
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
VisitorBase<TList>() {}
|
||||||
|
VisitorBase<TList>(const T& dest)
|
||||||
|
: VisitorBase<Tail>(dest) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||||
|
{ //
|
||||||
|
// T temp(obj)
|
||||||
|
// swap(destination_, temp) or destination_ = temp
|
||||||
|
//
|
||||||
|
this->destination_ = obj;
|
||||||
|
}
|
||||||
|
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot convert");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Visit(const Type& obj)
|
||||||
|
{
|
||||||
|
using namespace Loki;
|
||||||
|
enum { dispatch = Conversion<Type, T>::exists != 0 };
|
||||||
|
this->DoVisit(obj, Int2Type<dispatch>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VisitorBase< ::Loki::NullType >
|
||||||
|
: DestHolder
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
VisitorBase< ::Loki::NullType >() {}
|
||||||
|
VisitorBase< ::Loki::NullType >(const T& dest)
|
||||||
|
: DestHolder(dest) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef VisitorBase
|
||||||
|
<
|
||||||
|
typename VariantFrom::Types
|
||||||
|
>
|
||||||
|
VisitorBaseType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Visitor : public VisitorBaseType
|
||||||
|
{
|
||||||
|
Visitor() {}
|
||||||
|
|
||||||
|
explicit Visitor(const T& dest)
|
||||||
|
: VisitorBaseType(dest) {}
|
||||||
|
|
||||||
|
const T &GetDestination() const
|
||||||
|
{ return this->destination_; }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <class VariantFrom, class T>
|
||||||
|
struct ConverterTo
|
||||||
|
{
|
||||||
|
//private:
|
||||||
|
struct UnitBase : public VariantFrom::ConstStrictVisitor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
T destination_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Type, class Base>
|
||||||
|
struct Unit : public Base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||||
|
{
|
||||||
|
this->destination_ = obj;
|
||||||
|
}
|
||||||
|
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot convert");
|
||||||
|
}
|
||||||
|
virtual void Visit(const Type& obj)
|
||||||
|
{
|
||||||
|
using namespace Loki;
|
||||||
|
enum { dispatch = Conversion<Type, T>::exists != 0 };
|
||||||
|
this->DoVisit(obj, Int2Type<dispatch>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ::Loki::GenLinearHierarchy<
|
||||||
|
typename VariantFrom::Types,
|
||||||
|
Unit,
|
||||||
|
UnitBase > VisitorBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Visitor : public VisitorBase
|
||||||
|
{
|
||||||
|
const T &GetDestination() const
|
||||||
|
{ return this->destination_; }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct RawDataKeeper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef char RawBuffer_t[sizeof(T)];
|
||||||
|
enum ObjectState_e { eNone, ePreConstruct, ePostConstruct };
|
||||||
|
|
||||||
|
T &obj_;
|
||||||
|
ObjectState_e eObjState_;
|
||||||
|
RawBuffer_t bufferOrg_;
|
||||||
|
RawBuffer_t bufferNew_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetObj(const RawBuffer_t &buf) throw()
|
||||||
|
{
|
||||||
|
memcpy(&reinterpret_cast<char &>(obj_), buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetObj(RawBuffer_t &buf) throw()
|
||||||
|
{
|
||||||
|
memcpy(buf, &reinterpret_cast<const char &>(obj_), sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RawDataKeeper(T &obj)
|
||||||
|
: obj_(obj), eObjState_(eNone)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// add const U & version ?
|
||||||
|
template<typename U>
|
||||||
|
void ConstructNew(U &src)
|
||||||
|
{
|
||||||
|
assert(eObjState_ == eNone);
|
||||||
|
|
||||||
|
GetObj(bufferOrg_);
|
||||||
|
|
||||||
|
eObjState_ = ePreConstruct;
|
||||||
|
new (&obj_) T(src);
|
||||||
|
eObjState_ = ePostConstruct;
|
||||||
|
|
||||||
|
GetObj(bufferNew_);
|
||||||
|
SetObj(bufferOrg_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNew() throw()
|
||||||
|
{
|
||||||
|
assert(eObjState_ == ePostConstruct);
|
||||||
|
|
||||||
|
obj_.~T();
|
||||||
|
SetObj(bufferNew_);
|
||||||
|
eObjState_ = eNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RawDataKeeper()
|
||||||
|
{
|
||||||
|
switch(eObjState_)
|
||||||
|
{
|
||||||
|
case ePostConstruct:
|
||||||
|
SetObj(bufferNew_);
|
||||||
|
obj_.~T();
|
||||||
|
// fall
|
||||||
|
|
||||||
|
case ePreConstruct:
|
||||||
|
SetObj(bufferOrg_);
|
||||||
|
// fall
|
||||||
|
|
||||||
|
case eNone:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RawDataKeeper(const RawDataKeeper &);
|
||||||
|
RawDataKeeper& operator=(const RawDataKeeper &);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// based on Eric Fridman's safe_swap from boost Variant
|
||||||
|
//
|
||||||
|
// strong exception-safety guarantee.
|
||||||
|
//
|
||||||
|
// !WARNING!
|
||||||
|
// SafeSwap CANNOT be safely used in the general case if either
|
||||||
|
// argument's data members may be accessed concurrently.
|
||||||
|
//
|
||||||
|
template<typename T>
|
||||||
|
void SafeSwap(T &lhs, T &rhs)
|
||||||
|
{
|
||||||
|
typedef RawDataKeeper<T> RhsDataKeeper;
|
||||||
|
typedef RawDataKeeper<T> LhsDataKeeper;
|
||||||
|
|
||||||
|
RhsDataKeeper rhsKeeper(rhs);
|
||||||
|
rhsKeeper.ConstructNew(lhs);
|
||||||
|
|
||||||
|
LhsDataKeeper lhsKeeper(lhs);
|
||||||
|
lhsKeeper.ConstructNew(rhs);
|
||||||
|
|
||||||
|
rhsKeeper.SetNew();
|
||||||
|
lhsKeeper.SetNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// based on Eric Fridman's safe_assign from boost Variant
|
||||||
|
//
|
||||||
|
// strong exception-safety guarantee.
|
||||||
|
//
|
||||||
|
// !WARNING!
|
||||||
|
// SafeAssign CANNOT be safely used in the general case if either
|
||||||
|
// argument's data members may be accessed concurrently.
|
||||||
|
//
|
||||||
|
template<typename T, typename U>
|
||||||
|
void SafeAssign(T &lhs, const U &src)
|
||||||
|
{
|
||||||
|
typedef RawDataKeeper<T> LhsDataKeeper;
|
||||||
|
|
||||||
|
LhsDataKeeper lhsKeeper(lhs);
|
||||||
|
lhsKeeper.ConstructNew(src);
|
||||||
|
lhsKeeper.SetNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void SwapHelper(T &lhs, T &rhs)
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
swap(lhs, rhs);
|
||||||
|
}
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Variant
|
||||||
|
// Implements a discriminated union in C++
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class TList, class AlignedPODType = AlignedPOD<TList> >
|
||||||
|
class Variant
|
||||||
|
{
|
||||||
|
// VC7: fatal error C1067: compiler limit :
|
||||||
|
// debug information module size exceeded
|
||||||
|
// Therfore define this type here
|
||||||
|
typedef typename AlignedPODType::Result Align;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef TList Types;
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
// Initializes the Variant with a default-constructed object of the
|
||||||
|
// first type in the typelist
|
||||||
|
Variant()
|
||||||
|
{
|
||||||
|
typedef typename TList::Head T;
|
||||||
|
new(&buffer_[0]) T;
|
||||||
|
vptr_ = VTableImpl<T>::GetVPTR();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
Variant(const Variant& rhs)
|
||||||
|
{
|
||||||
|
(rhs.vptr_->clone_)(rhs, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Converting constructor; accepts any type in the typelist
|
||||||
|
// @@@ Suggested simple improvement: accept any type convertible to one of
|
||||||
|
// the types in the typelist. Use Loki::Conversion as a building block
|
||||||
|
template <class T>
|
||||||
|
void VariantConstruct(const T& val, double)
|
||||||
|
{
|
||||||
|
STATIC_CHECK((::Loki::TL::IndexOf<TList, T>::value >= 0),
|
||||||
|
Invalid_Type_Used_As_Initializer);
|
||||||
|
|
||||||
|
new(&buffer_[0]) T(val);
|
||||||
|
vptr_ = VTableImpl<T>::GetVPTR();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inter-Variant conversion constructor
|
||||||
|
// Current policy is: conversion succeeds iff the actual type of the source
|
||||||
|
// is one of the types accepted by the target
|
||||||
|
// @@@ Possible change: accept if the actual type of the source is
|
||||||
|
// convertible to one of the types accepted by the target. Problem to
|
||||||
|
// solve: handle ambiguities in a satisfactory manner. Suggestion: when
|
||||||
|
// in doubt, do closest to what the compiler would do.
|
||||||
|
template <class TList2, typename Align2>
|
||||||
|
void VariantConstruct(const Variant<TList2, Align2>& rhs, int)
|
||||||
|
{
|
||||||
|
typename Converter<Variant<TList2, Align2>, Variant>::Visitor v(*this);
|
||||||
|
typename Variant<TList2, Align2>::ConstStrictVisitor& visitor = v;
|
||||||
|
rhs.Accept(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// VC7 don't support partial ordering
|
||||||
|
// The constructor initialization section
|
||||||
|
// is empty which make it to use function instead
|
||||||
|
// without the int = 0 the explicit seems to confuse
|
||||||
|
// VC7 when the copy constructor should be selected
|
||||||
|
// Crazy stuff
|
||||||
|
template <class T>
|
||||||
|
explicit Variant(const T& val, int = 0)
|
||||||
|
{
|
||||||
|
VariantConstruct(val, int(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonic assignment operator
|
||||||
|
Variant& operator=(const Variant& rhs)
|
||||||
|
{
|
||||||
|
Private::SafeAssign(*this, rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Assignment operator from one of the allowed types
|
||||||
|
// This is necessary because the constructor is explicit
|
||||||
|
template <class T>
|
||||||
|
void VariantAssign(const T& rhs, double)
|
||||||
|
{
|
||||||
|
Private::SafeAssign(*this, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignment from another Variant instantiation
|
||||||
|
template <class TList2, typename Align2>
|
||||||
|
void VariantAssign(const Variant<TList2, Align2>& rhs, int)
|
||||||
|
{
|
||||||
|
Private::SafeAssign(*this, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// VC7 don't support partial ordering
|
||||||
|
template <class T>
|
||||||
|
Variant& operator=(const T& rhs)
|
||||||
|
{
|
||||||
|
// Both VariantAssign are the same in this implementation
|
||||||
|
VariantAssign(rhs, int(0));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~
|
||||||
|
~Variant()
|
||||||
|
{
|
||||||
|
(vptr_->destroy_)(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visitors definitions
|
||||||
|
// @@@ Possible improvement: add defintions of visitor who return
|
||||||
|
// something else than void
|
||||||
|
|
||||||
|
typedef ::Loki::Visitor<TList, void> StrictVisitor;
|
||||||
|
typedef ::Loki::Visitor<typename MakeConst<TList>::Result, void>
|
||||||
|
ConstStrictVisitor;
|
||||||
|
typedef ::Loki::NonStrictVisitor<TList, void> NonStrictVisitor;
|
||||||
|
typedef ::Loki::NonStrictVisitor<typename MakeConst<TList>::Result, void>
|
||||||
|
ConstNonStrictVisitor;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// VTable structure
|
||||||
|
// The essential component of the fake vtable idiom, VTable contains
|
||||||
|
// pointers to functions, pointers that will be filled up with addresses
|
||||||
|
// of functions in VTableImpl
|
||||||
|
|
||||||
|
struct VTable
|
||||||
|
{
|
||||||
|
const std::type_info& (*typeId_)();
|
||||||
|
void (*destroy_)(const Variant&);
|
||||||
|
void (*clone_)(const Variant&, Variant&);
|
||||||
|
void (*swap_)(void* lhs, void* rhs);
|
||||||
|
void (*accept_)(Variant&, StrictVisitor&);
|
||||||
|
void (*acceptConst_)(const Variant&, ConstStrictVisitor&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// VTable concrete implementations
|
||||||
|
// VTableImpl<T> contains definitions for all of a VTable's pointer to
|
||||||
|
// functions.
|
||||||
|
|
||||||
|
// VC7 thinks that Variant inside VTableImpl is template
|
||||||
|
typedef Variant VariantType;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct VTableImpl
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static const std::type_info& TypeId()
|
||||||
|
{
|
||||||
|
return typeid(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Destroy(const VariantType& var)
|
||||||
|
{
|
||||||
|
const T& data = *reinterpret_cast<const T*>(&var.buffer_[0]);
|
||||||
|
(void)data.~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Swap(void* lhs, void* rhs)
|
||||||
|
{
|
||||||
|
Private::SwapHelper(*static_cast<T*>(lhs), *static_cast<T*>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Clone(const VariantType& src, VariantType& dest)
|
||||||
|
{
|
||||||
|
new(&dest.buffer_[0]) T(
|
||||||
|
*reinterpret_cast<const T*>(&src.buffer_[0]));
|
||||||
|
dest.vptr_ = src.vptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Accept(VariantType& var, StrictVisitor& visitor)
|
||||||
|
{
|
||||||
|
typedef typename StrictVisitor::ReturnType RType;
|
||||||
|
::Loki::Visitor<T,RType> &v = visitor;
|
||||||
|
|
||||||
|
v.Visit(*reinterpret_cast<T*>(&var.buffer_[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AcceptConst(const VariantType& var, ConstStrictVisitor& visitor)
|
||||||
|
{
|
||||||
|
typedef typename ConstStrictVisitor::ReturnType RType;
|
||||||
|
::Loki::Visitor<const T,RType> &v = visitor;
|
||||||
|
|
||||||
|
v.Visit(*reinterpret_cast<const T*>(&var.buffer_[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const VTable *GetVPTR()
|
||||||
|
{
|
||||||
|
static const VTable vTbl_ =
|
||||||
|
{
|
||||||
|
&TypeId,
|
||||||
|
&Destroy,
|
||||||
|
&Clone,
|
||||||
|
&Swap,
|
||||||
|
&Accept,
|
||||||
|
&AcceptConst,
|
||||||
|
};
|
||||||
|
|
||||||
|
return &vTbl_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> friend struct VTableImpl;
|
||||||
|
|
||||||
|
private: // should be private; some compilers prefer 'public' :o}
|
||||||
|
|
||||||
|
enum { neededSize = MaxSize<TList>::result };
|
||||||
|
|
||||||
|
VTable const * vptr_;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Align dummy_;
|
||||||
|
char buffer_[neededSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void swap(Variant& rhs)
|
||||||
|
{
|
||||||
|
if (this->TypeId() == rhs.TypeId())
|
||||||
|
{
|
||||||
|
(vptr_->swap_)(this->buffer_, rhs.buffer_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Private::SafeSwap(*this, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::type_info& TypeId() const
|
||||||
|
{
|
||||||
|
return (vptr_->typeId_)();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> T* GetPtr()
|
||||||
|
{
|
||||||
|
return TypeId() == typeid(T)
|
||||||
|
? reinterpret_cast<T*>(&buffer_[0])
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> const T* GetPtr() const
|
||||||
|
{
|
||||||
|
return TypeId() == typeid(T)
|
||||||
|
? reinterpret_cast<const T*>(&buffer_[0])
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> T& Get()
|
||||||
|
{
|
||||||
|
T* p = GetPtr<T>();
|
||||||
|
if (!p) throw std::runtime_error("Variant::Get() Invalid variant type");
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> const T& Get() const
|
||||||
|
{
|
||||||
|
const T* p = GetPtr<T>();
|
||||||
|
if (!p) throw std::runtime_error("Variant::Get() const Invalid variant type");
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visitation primitives
|
||||||
|
// Although there are four visitor types, only two Accept functions are
|
||||||
|
// necessary, because the non-strict visitors inherit the strict visitors
|
||||||
|
|
||||||
|
void Accept(StrictVisitor& visitor)
|
||||||
|
{
|
||||||
|
(vptr_->accept_)(*this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Accept(ConstStrictVisitor& visitor) const
|
||||||
|
{
|
||||||
|
(vptr_->acceptConst_)(*this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the value of a Variant converted to a specific type
|
||||||
|
|
||||||
|
template <class To> To ConvertTo() const
|
||||||
|
{
|
||||||
|
typename ConverterTo<Variant, To>::Visitor v;
|
||||||
|
ConstStrictVisitor& visitor = v;
|
||||||
|
this->Accept(visitor);
|
||||||
|
return v.GetDestination();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes the type of a Variant in-place
|
||||||
|
|
||||||
|
template <class To> void ChangeType()
|
||||||
|
{
|
||||||
|
Variant(this->ConvertTo<To>()).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// July 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
328
MSVC/1300/Visitor.h
Normal file
328
MSVC/1300/Visitor.h
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The Loki Library
|
||||||
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
|
// This code accompanies the book:
|
||||||
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
|
// permission notice appear in supporting documentation.
|
||||||
|
// The author or Addison-Welsey Longman make no representations about the
|
||||||
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
|
// without express or implied warranty.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Last update: May 19, 2002
|
||||||
|
|
||||||
|
#ifndef VISITOR_INC_
|
||||||
|
#define VISITOR_INC_
|
||||||
|
|
||||||
|
#include "Typelist.h"
|
||||||
|
#include "HierarchyGenerators.h"
|
||||||
|
|
||||||
|
namespace Loki
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template BaseVisitor
|
||||||
|
// The base class of any Acyclic Visitor
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class BaseVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~BaseVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Visitor
|
||||||
|
// Forward decleration
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T, typename R = void>
|
||||||
|
class Visitor;
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
// for some reason VC7 needs the base definition altough not in use
|
||||||
|
template <typename TListTag>
|
||||||
|
struct VisitorHelper1
|
||||||
|
{
|
||||||
|
template <typename T, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TListTag>
|
||||||
|
struct VisitorHelper2
|
||||||
|
{
|
||||||
|
template <typename T, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VisitorHelper1<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template <class TList, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef Visitor<typename TList::Head, R> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VisitorHelper2<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template <class TList, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<typename Tail>
|
||||||
|
struct In1
|
||||||
|
{
|
||||||
|
typedef Visitor<typename TList::Tail, R> Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct In1<NullType>
|
||||||
|
{
|
||||||
|
struct Result {};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename In1<typename TList::Tail>::Result Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VisitorHelper1<TL::NoneList_tag>
|
||||||
|
{
|
||||||
|
template <class T, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
struct Result
|
||||||
|
{
|
||||||
|
typedef R ReturnType;
|
||||||
|
virtual ReturnType Visit(T&) = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VisitorHelper2<TL::NoneList_tag>
|
||||||
|
{
|
||||||
|
template <class T, typename R>
|
||||||
|
struct In { struct Result {}; };
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template Visitor
|
||||||
|
// The building block of Acyclic Visitor
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T, typename R>
|
||||||
|
class Visitor
|
||||||
|
: public Private::VisitorHelper1
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, R>::Result
|
||||||
|
|
||||||
|
, public Private::VisitorHelper2
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<T>::type_tag
|
||||||
|
>
|
||||||
|
::template In<T, R>::Result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef R ReturnType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template BaseVisitorImpl
|
||||||
|
// Implements non-strict visitation (you can implement only part of the Visit
|
||||||
|
// functions)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <class TList, typename R = void>
|
||||||
|
class BaseVisitorImpl;
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
// for some reason VC7 needs the base definition altough not in use
|
||||||
|
template<typename TListTag>
|
||||||
|
struct BaseVisitorImplHelper
|
||||||
|
{
|
||||||
|
template <typename T, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct BaseVisitorImplHelper<TL::Typelist_tag>
|
||||||
|
{
|
||||||
|
template <typename TList, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
typedef BaseVisitorImpl<TList, R> Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct BaseVisitorImplHelper<TL::NullType_tag>
|
||||||
|
{
|
||||||
|
template <typename TList, typename R>
|
||||||
|
struct In
|
||||||
|
{
|
||||||
|
struct Result {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Private
|
||||||
|
|
||||||
|
template <class TList, typename R>
|
||||||
|
class BaseVisitorImpl
|
||||||
|
: public Visitor<typename TList::Head, R>
|
||||||
|
|
||||||
|
, public Private::BaseVisitorImplHelper
|
||||||
|
<
|
||||||
|
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
||||||
|
>
|
||||||
|
::template In<typename TList::Tail, R>::Result
|
||||||
|
{
|
||||||
|
ASSERT_TYPELIST(TList);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// using BaseVisitorImpl<Tail, R>::Visit;
|
||||||
|
|
||||||
|
virtual R Visit(typename TList::Head&)
|
||||||
|
{ return R(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template NonStrictVisitor
|
||||||
|
// Implements non-strict visitation (you can implement only part of the Visit
|
||||||
|
// functions)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T, class Base>
|
||||||
|
struct NonStrictVisitorUnit : public Base
|
||||||
|
{
|
||||||
|
typedef typename Base::ReturnType ReturnType;
|
||||||
|
ReturnType Visit(T&)
|
||||||
|
{
|
||||||
|
return ReturnType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class TList, typename R = void>
|
||||||
|
class NonStrictVisitor
|
||||||
|
: public GenLinearHierarchy<
|
||||||
|
TList,
|
||||||
|
NonStrictVisitorUnit,
|
||||||
|
Visitor<TList, R> >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template BaseVisitable
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename R, typename Visited>
|
||||||
|
struct DefaultCatchAll
|
||||||
|
{
|
||||||
|
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
||||||
|
{ return R(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template BaseVisitable
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename R = void,
|
||||||
|
template <typename, class> class CatchAll = DefaultCatchAll
|
||||||
|
>
|
||||||
|
class BaseVisitable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef R ReturnType;
|
||||||
|
virtual ~BaseVisitable() {}
|
||||||
|
virtual ReturnType Accept(BaseVisitor&) = 0;
|
||||||
|
|
||||||
|
protected: // give access only to the hierarchy
|
||||||
|
template <class T>
|
||||||
|
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
||||||
|
{
|
||||||
|
// Apply the Acyclic Visitor
|
||||||
|
if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
|
||||||
|
{
|
||||||
|
return p->Visit(visited);
|
||||||
|
}
|
||||||
|
return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// macro DEFINE_VISITABLE
|
||||||
|
// Put it in every class that you want to make visitable (in addition to
|
||||||
|
// deriving it from BaseVisitable<R>
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define DEFINE_VISITABLE() \
|
||||||
|
virtual ReturnType Accept(BaseVisitor& guest) \
|
||||||
|
{ return AcceptImpl(*this, guest); }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// class template CyclicVisitor
|
||||||
|
// Put it in every class that you want to make visitable (in addition to
|
||||||
|
// deriving it from BaseVisitable<R>
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename R, class TList>
|
||||||
|
class CyclicVisitor : public Visitor<TList, R>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef R ReturnType;
|
||||||
|
// using Visitor<TList, R>::Visit;
|
||||||
|
|
||||||
|
virtual ~CyclicVisitor() {}
|
||||||
|
|
||||||
|
template <class Visited>
|
||||||
|
ReturnType GenericVisit(Visited& host)
|
||||||
|
{
|
||||||
|
Visitor<Visited, ReturnType>& subObj = *this;
|
||||||
|
return subObj.Visit(host);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// macro DEFINE_CYCLIC_VISITABLE
|
||||||
|
// Put it in every class that you want to make visitable by a cyclic visitor
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
|
||||||
|
virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
|
||||||
|
{ return guest.GenericVisit(*this); }
|
||||||
|
} // namespace Loki
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Change log:
|
||||||
|
// March 20: add default argument DefaultCatchAll to BaseVisitable
|
||||||
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // VISITOR_INC_
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
MSVC7
|
Rani Sharoni
|
||||||
Jonathan H. Lundquist
|
|
||||||
Shannon G. Barber (aka Magmai Kai Holmlor)
|
|
18
MSVC/1300/readme.txt
Normal file
18
MSVC/1300/readme.txt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Last update: May 19, 2002
|
||||||
|
|
||||||
|
Directions:
|
||||||
|
|
||||||
|
To use Loki, simply extract the files from the archive, give your compiler access to their path, and include them appropriately in your code via #include.
|
||||||
|
|
||||||
|
If you use the small object allocator directly or indirectly (through the Functor class) you must add SmallObj.cpp to your project/makefile.
|
||||||
|
|
||||||
|
If you use Singletons with longevity you must add Singleton.cpp to your project/makefile.
|
||||||
|
|
||||||
|
Compatibility:
|
||||||
|
This is ported version of Loki to VC.NET (VC7 - 9466) it is only targeted for this compiler.
|
||||||
|
To compile your sources with the original Loki you'll have to place it in a separate directory.
|
||||||
|
|
||||||
|
More info:
|
||||||
|
|
||||||
|
http://moderncppdesign.com
|
||||||
|
http://www.geocities.com/rani_sharoni/LokiPort.html
|
|
@ -24,8 +24,14 @@ namespace Loki
|
||||||
// Helper structure for the STATIC_CHECK macro
|
// Helper structure for the STATIC_CHECK macro
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<int> struct CompileTimeError;
|
template<bool CompileTimeAssertion>
|
||||||
template<> struct CompileTimeError<true> {};
|
struct CompileTimeError;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct CompileTimeError<true>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -38,14 +44,14 @@ namespace Loki
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define STATIC_CHECK(expr, msg) \
|
#define STATIC_CHECK(expr, msg) \
|
||||||
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
|
typedef char ERROR_##msg[1][(expr)]
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
|
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
|
||||||
// definition
|
// definition
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
|
// July 09, 2002: improved for favor of VC diagnostic and usage
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif // STATIC_CHECK_INC_
|
#endif // STATIC_CHECK_INC_
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue