move directory: MSVC->include/noncc
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@157 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
33e8c0a9d2
commit
339dcd4233
52 changed files with 22874 additions and 0 deletions
223
include/noncc/MSVC/1200/AbstractFactory.h
Executable file
223
include/noncc/MSVC/1200/AbstractFactory.h
Executable file
|
@ -0,0 +1,223 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Feb 20, 2003
|
||||
// replaced pointer-dummy parameters with Type2Type-parameters.
|
||||
// See readme.txt (notes: C) if you don't know why the dummy parameters are needed
|
||||
//
|
||||
// replaced all template template parameters with 'normal' parameters
|
||||
// For each Factory-Unit there is now a wrapper-class (non template class)
|
||||
// containing a nested template class called In which
|
||||
// provides a typedef (type) to the real unit-class.
|
||||
// Use one of the wrapper-classes to instantiate a factory.
|
||||
//
|
||||
// Covariant return types had to go, too.
|
||||
|
||||
#ifndef ABSTRACTFACTORY_INC_
|
||||
#define ABSTRACTFACTORY_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeManip.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
#include "MSVC6Helpers.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#define ETAS_HELPER(Type) (::Loki::Type2Type<Type>())
|
||||
|
||||
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() {}
|
||||
};
|
||||
|
||||
// Wrapper for AbstractFactoryUnit.
|
||||
struct AbstractFactoryUnitWrapper
|
||||
{
|
||||
template <class T>
|
||||
struct In
|
||||
{
|
||||
typedef AbstractFactoryUnit<T> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactory
|
||||
// Defines an Abstract Factory interface starting from a typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// VC 6.0 changes:
|
||||
// Because the VC 6.0 does not support explicit template argument specification (14.8.1)
|
||||
// the member-function Create takes a dummy argument of type Type2Type<T> whose sole
|
||||
// responsibility is to help the compiler in deducing the type of T.
|
||||
// Using this port the call:
|
||||
// ConcProduct* p = aFactory.Create<ConcProduct>();
|
||||
// therefore becomes:
|
||||
// ConcProduct* p = aFactory.Create(Type2Type<ConcProduct>());
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
class Unit = AbstractFactoryUnitWrapper
|
||||
>
|
||||
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
|
||||
{
|
||||
public:
|
||||
typedef TList ProductList;
|
||||
|
||||
template <class T> T* Create(Type2Type<T>)
|
||||
{
|
||||
ApplyInnerType<Unit, T>::type& 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;
|
||||
// VC does not support covariant return types
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
return new ConcreteProduct;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for OpNewFactoryUnit
|
||||
struct OpNewFactoryUnitWrapper
|
||||
{
|
||||
template <class T, class Base>
|
||||
struct In
|
||||
{
|
||||
typedef OpNewFactoryUnit<T, Base> type;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PrototypeFactoryUnit
|
||||
// Creates an object by cloning a prototype
|
||||
// There is a difference between the implementation herein and the one described
|
||||
// in the book: GetPrototype and SetPrototype use the helper friend
|
||||
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
|
||||
// name hiding issues. Plus, GetPrototype takes a reference to pointer
|
||||
// instead of returning the pointer by value.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class PrototypeFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
|
||||
PrototypeFactoryUnit(AbstractProduct* p = 0)
|
||||
: pPrototype_(p)
|
||||
{}
|
||||
|
||||
friend void DoGetPrototype(const PrototypeFactoryUnit& me,
|
||||
AbstractProduct*& pPrototype)
|
||||
{ pPrototype = me.pPrototype_; }
|
||||
|
||||
friend void DoSetPrototype(PrototypeFactoryUnit& me,
|
||||
AbstractProduct* pObj)
|
||||
{ me.pPrototype_ = pObj; }
|
||||
|
||||
template <class U>
|
||||
void GetPrototype(U*& p)
|
||||
{ return DoGetPrototype(*this, p); }
|
||||
|
||||
template <class U>
|
||||
void SetPrototype(U* pObj)
|
||||
{ DoSetPrototype(*this, pObj); }
|
||||
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
assert(pPrototype_);
|
||||
// vc does not support covariant return types thus
|
||||
// Clone *always* returns a base-pointer.
|
||||
// if DoCreate is called from a ConcreteFactory-object we
|
||||
// need to down-cast.
|
||||
// Is the static_cast always safe?
|
||||
return static_cast<AbstractProduct*>(pPrototype_->Clone());
|
||||
}
|
||||
|
||||
private:
|
||||
AbstractProduct* pPrototype_;
|
||||
};
|
||||
|
||||
// Wrapper for PrototypeFactoryUnit
|
||||
struct PrototypeFactoryUnitWrapper
|
||||
{
|
||||
template <class T, class Base>
|
||||
struct In
|
||||
{
|
||||
typedef PrototypeFactoryUnit<T, Base> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConcreteFactory
|
||||
// Implements an AbstractFactory interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractFact,
|
||||
class Creator = OpNewFactoryUnit,
|
||||
class TList = /*VC 6.0 does not like typename here*/ 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!!!
|
||||
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// Feb 20, 2003: replaced pointer-dummy parameters with Type2Type-parameters. B.K.
|
||||
// September 25, 2004: Fixed bug in PrototypeFactoryUnit::GetPrototype, thanks
|
||||
// to a bug report submitted by funcall.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ABSTRACTFACTORY_INC_
|
335
include/noncc/MSVC/1200/AssocVector.h
Executable file
335
include/noncc/MSVC/1200/AssocVector.h
Executable 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() || operator()(val.first, i->first))
|
||||
{
|
||||
i = Base::insert(i, val);
|
||||
found = false;
|
||||
}
|
||||
return std::make_pair(i, !found);
|
||||
}
|
||||
|
||||
iterator insert(iterator pos, const value_type& val)
|
||||
{
|
||||
if (pos != end() && operator()(*pos, val) &&
|
||||
(pos == end() - 1 ||
|
||||
!operator()(val, pos[1]) &&
|
||||
operator()(pos[1], val)))
|
||||
{
|
||||
return Base::insert(pos, val);
|
||||
}
|
||||
return insert(val).first;
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
{ for (; first != last; ++first) insert(*first); }
|
||||
|
||||
void erase(iterator pos)
|
||||
{ Base::erase(pos); }
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
iterator i(find(k));
|
||||
if (i == end()) return 0;
|
||||
erase(i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void erase(iterator first, iterator last)
|
||||
{ Base::erase(first, last); }
|
||||
|
||||
void swap(AssocVector& other)
|
||||
{
|
||||
using std::swap;
|
||||
Base::swap(other);
|
||||
MyCompare& me = *this;
|
||||
MyCompare& rhs = other;
|
||||
swap(me, rhs);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{ Base::clear(); }
|
||||
|
||||
// observers:
|
||||
key_compare key_comp() const
|
||||
{ return *this; }
|
||||
|
||||
value_compare value_comp() const
|
||||
{
|
||||
const key_compare& comp = *this;
|
||||
return value_compare(comp);
|
||||
}
|
||||
|
||||
// 23.3.1.3 map operations:
|
||||
iterator find(const key_type& k)
|
||||
{
|
||||
iterator i(lower_bound(k));
|
||||
if (i != end() && operator()(k, i->first))
|
||||
{
|
||||
i = end();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
const_iterator i(lower_bound(k));
|
||||
if (i != end() && operator()(k, i->first))
|
||||
{
|
||||
i = end();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{ return find(k) != end(); }
|
||||
|
||||
iterator lower_bound(const key_type& k)
|
||||
{
|
||||
MyCompare& me = *this;
|
||||
return std::lower_bound(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type& k) const
|
||||
{
|
||||
const MyCompare& me = *this;
|
||||
return std::lower_bound(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type& k)
|
||||
{
|
||||
MyCompare& me = *this;
|
||||
return std::upper_bound(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type& k) const
|
||||
{
|
||||
const MyCompare& me = *this;
|
||||
return std::upper_bound(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const key_type& k)
|
||||
{
|
||||
MyCompare& me = *this;
|
||||
return std::equal_range(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(
|
||||
const key_type& k) const
|
||||
{
|
||||
const MyCompare& me = *this;
|
||||
return std::equal_range(begin(), end(), k, me);
|
||||
}
|
||||
|
||||
friend bool operator==(const AssocVector& lhs, const AssocVector& rhs)
|
||||
{
|
||||
const Base& me = lhs;
|
||||
return me == rhs;
|
||||
}
|
||||
|
||||
bool operator<(const AssocVector& rhs) const
|
||||
{
|
||||
const Base& me = *this;
|
||||
const Base& yo = rhs;
|
||||
return me < yo;
|
||||
}
|
||||
|
||||
friend bool operator!=(const AssocVector& lhs, const AssocVector& rhs)
|
||||
{ return !(lhs == rhs); }
|
||||
|
||||
friend bool operator>(const AssocVector& lhs, const AssocVector& rhs)
|
||||
{ return rhs < lhs; }
|
||||
|
||||
friend bool operator>=(const AssocVector& lhs, const AssocVector& rhs)
|
||||
{ return !(lhs < rhs); }
|
||||
|
||||
friend bool operator<=(const AssocVector& lhs, const AssocVector& rhs)
|
||||
{ return !(rhs < lhs); }
|
||||
};
|
||||
|
||||
// specialized algorithms:
|
||||
template <class K, class V, class C, class A>
|
||||
void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
|
||||
{ lhs.swap(rhs); }
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// May 20, 2001: change operator= - credit due to Cristoph Koegl
|
||||
// June 11, 2001: remove paren in equal_range - credit due to Cristoph Koegl
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// January 22, 2002: fixed operator= - credit due to Tom Hyer
|
||||
// June 25, 2002: fixed template insert() - credit due to Robert Minsk
|
||||
// June 27, 2002: fixed member swap() - credit due to David Brookman
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ASSOCVECTOR_INC_
|
150
include/noncc/MSVC/1200/DataGenerators.h
Executable file
150
include/noncc/MSVC/1200/DataGenerators.h
Executable file
|
@ -0,0 +1,150 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Data Generator by Shannon Barber
|
||||
// This code DOES NOT accompany the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
//
|
||||
// Code covered by the MIT License
|
||||
// The author makes no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Mar 04, 2003
|
||||
// MSVC 6.0 version
|
||||
|
||||
#ifndef DATAGENERATORS_H
|
||||
#define DATAGENERATORS_H
|
||||
#include "Typelist.h"
|
||||
#include "MSVC6Helpers.h"
|
||||
namespace Loki
|
||||
{
|
||||
namespace TL
|
||||
{
|
||||
template<typename T>
|
||||
struct nameof_type
|
||||
{
|
||||
const char* operator()()
|
||||
{
|
||||
return typeid(T).name();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct sizeof_type
|
||||
{
|
||||
size_t operator()()
|
||||
{
|
||||
return sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
// wrappers to workaround the need for template template parameters
|
||||
struct nameof_type_wrapper
|
||||
{
|
||||
template <class T>
|
||||
struct In
|
||||
{
|
||||
typedef nameof_type<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
struct sizeof_type_wrapper
|
||||
{
|
||||
template <class T>
|
||||
struct In
|
||||
{
|
||||
typedef sizeof_type<T> type;
|
||||
};
|
||||
|
||||
};
|
||||
template <class TList, class GenFunc>
|
||||
struct IterateTypes;
|
||||
namespace Private
|
||||
{
|
||||
// Specialization for a general typelist
|
||||
template <unsigned Tag>
|
||||
struct IterateTypesImpl
|
||||
{
|
||||
template <class TList, class GenFunc>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::Head T1;
|
||||
typedef typename TList::Tail T2;
|
||||
|
||||
typedef IterateTypes<T1, GenFunc> head_t;
|
||||
head_t head;
|
||||
typedef IterateTypes<T2, GenFunc> tail_t;
|
||||
tail_t tail;
|
||||
|
||||
template<class II>
|
||||
void operator()(II ii)
|
||||
{
|
||||
head.operator()(ii);
|
||||
tail.operator()(ii);
|
||||
}
|
||||
protected:
|
||||
~In() {}
|
||||
};
|
||||
};
|
||||
|
||||
// Specialization for a single type
|
||||
template <>
|
||||
struct IterateTypesImpl<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class AtomicType, class GenFunc>
|
||||
struct In
|
||||
{
|
||||
template<class II>
|
||||
void operator()(II ii)
|
||||
{
|
||||
typedef typename Loki::ApplyInnerType<GenFunc, AtomicType>::type gFunc;
|
||||
gFunc genfunc;
|
||||
*ii = genfunc();
|
||||
++ii; //Is this even needed?
|
||||
}
|
||||
protected:
|
||||
~In() {}
|
||||
};
|
||||
};
|
||||
|
||||
// Specialization for NullType
|
||||
template <>
|
||||
struct IterateTypesImpl<TL::Private::NullType_ID>
|
||||
{
|
||||
template <class T, class GenFunc>
|
||||
struct In
|
||||
{
|
||||
template<class II>
|
||||
void operator()(II ii)
|
||||
{}
|
||||
protected:
|
||||
~In() {}
|
||||
};
|
||||
};
|
||||
} // end ns Private
|
||||
|
||||
template <class TList, class GenFunc>
|
||||
struct IterateTypes : public
|
||||
Private::IterateTypesImpl
|
||||
<
|
||||
TL::Private::IsTypelist<TList>::type_id
|
||||
>::template In<TList, GenFunc>
|
||||
{};
|
||||
|
||||
template<typename Types, class UnitFunc, typename II>
|
||||
void iterate_types(II ii)
|
||||
{
|
||||
Loki::TL::IterateTypes<Types, UnitFunc> it;
|
||||
it(ii);
|
||||
}
|
||||
}//ns TL
|
||||
}//ns Loki
|
||||
|
||||
#endif //DATAGENERATORS_H
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// 9/20/02 Named changed from GenData to IterateTypes
|
||||
// 10/8/02 insertion iterators are passed-by-value, not by-reference (oops)
|
||||
// 03/04/03 ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// 03/06/03 added protected destructors to private implementation classes B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
37
include/noncc/MSVC/1200/EmptyType.h
Executable file
37
include/noncc/MSVC/1200/EmptyType.h
Executable 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_
|
151
include/noncc/MSVC/1200/Factory.h
Executable file
151
include/noncc/MSVC/1200/Factory.h
Executable file
|
@ -0,0 +1,151 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Last update: Feb 22, 2003
|
||||
//
|
||||
//
|
||||
// The default error policy is no longer a template-class
|
||||
|
||||
#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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DefaultFactoryError
|
||||
{
|
||||
struct Exception : public std::exception
|
||||
{
|
||||
const char* what() const throw() { return "Unknown Type"; }
|
||||
};
|
||||
|
||||
template <typename IdentifierType, class AbstractProduct>
|
||||
static AbstractProduct* OnUnknownType(IdentifierType s,Type2Type<AbstractProduct>)
|
||||
{
|
||||
throw Exception();
|
||||
return (AbstractProduct*) 0;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Factory
|
||||
// Implements a generic object factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
typename IdentifierType,
|
||||
typename ProductCreator = AbstractProduct* (*)(),
|
||||
class FactoryErrorPolicy = DefaultFactoryError
|
||||
>
|
||||
class Factory
|
||||
: public FactoryErrorPolicy
|
||||
{
|
||||
public:
|
||||
bool Register(const IdentifierType& id, ProductCreator creator)
|
||||
{
|
||||
return associations_.insert(
|
||||
IdToProductMap::value_type(id, creator)).second;
|
||||
}
|
||||
|
||||
bool Unregister(const IdentifierType& id)
|
||||
{
|
||||
return associations_.erase(id) == 1;
|
||||
}
|
||||
|
||||
AbstractProduct* CreateObject(const IdentifierType& id)
|
||||
{
|
||||
typename IdToProductMap::iterator i = associations_.find(id);
|
||||
if (i != associations_.end())
|
||||
{
|
||||
return (i->second)();
|
||||
}
|
||||
return OnUnknownType(id, Type2Type<AbstractProduct>());
|
||||
}
|
||||
|
||||
private:
|
||||
typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
|
||||
IdToProductMap associations_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CloneFactory
|
||||
// Implements a generic cloning factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
class ProductCreator =
|
||||
AbstractProduct* (*)(const AbstractProduct*),
|
||||
|
||||
class FactoryErrorPolicy = DefaultFactoryError
|
||||
>
|
||||
class CloneFactory
|
||||
: public FactoryErrorPolicy
|
||||
{
|
||||
public:
|
||||
bool Register(const TypeInfo& ti, ProductCreator creator)
|
||||
{
|
||||
return associations_.insert(
|
||||
IdToProductMap::value_type(ti, creator)).second;
|
||||
}
|
||||
|
||||
bool Unregister(const TypeInfo& id)
|
||||
{
|
||||
return associations_.erase(id) == 1;
|
||||
}
|
||||
|
||||
AbstractProduct* CreateObject(const AbstractProduct* model)
|
||||
{
|
||||
if (model == 0) return 0;
|
||||
|
||||
typename IdToProductMap::iterator i =
|
||||
associations_.find(typeid(*model));
|
||||
if (i != associations_.end())
|
||||
{
|
||||
return (i->second)(model);
|
||||
}
|
||||
return OnUnknownType(TypeInfo(typeid(*model)),Type2Type<AbstractProduct>());
|
||||
}
|
||||
|
||||
private:
|
||||
typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
|
||||
IdToProductMap associations_;
|
||||
};
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 08, 2002: replaced const_iterator with iterator so that self-modifying
|
||||
// ProductCreators are supported. Also, added a throw() spec to what().
|
||||
// Credit due to Jason Fischl.
|
||||
// Oct 24, 2002: ported to MSVC 6 by Benjamin Kaufmann.
|
||||
// Note: The default error policy is no longer a template-class.
|
||||
// Feb 22, 2003: Added missing parameter to OnUnknownType B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // FACTORY_INC_
|
2332
include/noncc/MSVC/1200/Functor.h
Executable file
2332
include/noncc/MSVC/1200/Functor.h
Executable file
File diff suppressed because it is too large
Load diff
2123
include/noncc/MSVC/1200/FunctorOld.h
Executable file
2123
include/noncc/MSVC/1200/FunctorOld.h
Executable file
File diff suppressed because it is too large
Load diff
520
include/noncc/MSVC/1200/HierarchyGenerators.h
Executable file
520
include/noncc/MSVC/1200/HierarchyGenerators.h
Executable file
|
@ -0,0 +1,520 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Mar 08, 2003
|
||||
|
||||
|
||||
#ifndef HIERARCHYGENERATORS_INC_
|
||||
#define HIERARCHYGENERATORS_INC_
|
||||
|
||||
#define IS_TYPELIST(TList) TL::Private::IsTypelist<TList>
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeTraits.h"
|
||||
#include "EmptyType.h"
|
||||
#include "MSVC6Helpers.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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// VC 6.0 changes:
|
||||
// * Unit is no longer a template template parameter.
|
||||
// * For every concrete unit-template there must be a normal class containing
|
||||
// a nested-template class called In. In should only contain a typedef to the
|
||||
// concrete Unit.
|
||||
//
|
||||
// Using the originial library one would write something like this:
|
||||
// class Foo {};
|
||||
// template <class T> struct TestUnit {};
|
||||
// void Func(TestUnit<Foo>);
|
||||
// int main()
|
||||
// {
|
||||
// GenScatterHierarchy<Typelist<Foo, NullType>, TestUnit> obj;
|
||||
// Func(obj); // calls Func(TestUnit<Foo>)
|
||||
// }
|
||||
//
|
||||
// Using this port the code would become:
|
||||
// class Foo {};
|
||||
// template <class T> struct TestUnit {};
|
||||
// struct TestUnitWrapper
|
||||
// {
|
||||
// template <class T> struct In {typedef TestUnit<T> type};
|
||||
// };
|
||||
// void Func(TestUnit<Foo>);
|
||||
// int main()
|
||||
// {
|
||||
// GenScatterHierarchy<Typelist<Foo, NullType>, TestUnitWrapper> obj;
|
||||
// Func(obj); // calls Func(TestUnit<Foo>)
|
||||
// }
|
||||
//
|
||||
// Not very nice, i know :-(
|
||||
//
|
||||
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
|
||||
// (http://lists.boost.org/MailArchives/boost/msg20915.php)
|
||||
//
|
||||
// Update:
|
||||
// -------
|
||||
// The first version of GenScatterHierarchy did not work with typelists
|
||||
// containing equal types. The MSVC 6.0 erroneously complains about
|
||||
// inaccessible base-classes (error C2584).
|
||||
// This new version adds Dummy-classes to the left branch of the generated
|
||||
// hierarchy to workaround this VC-Bug.
|
||||
// It creates hierarchies like this:
|
||||
//
|
||||
// Holder<int> NullType
|
||||
// \ /
|
||||
//Holder<int> GenScatter<int> GenScatter<NullType>
|
||||
// \ \ /
|
||||
//VC_InaccessibleBase InheritFromTo
|
||||
// \ |
|
||||
//GenScatter<int> GenScatter<TYPELIST_1(int)>
|
||||
// \ /
|
||||
// InheritFromTo
|
||||
// |
|
||||
// |
|
||||
//GenScatter<TYPELIST_2(int, int)>
|
||||
//
|
||||
// Of course this version of GenScatterHierarchy generates a lot more
|
||||
// classes (5*n) than Alexandrescu's original implementation (3*n)
|
||||
//
|
||||
|
||||
template <class TList, class Unit> class GenScatterHierarchy;
|
||||
namespace Private
|
||||
{
|
||||
|
||||
template <class T, class U>
|
||||
struct InheritFromTwo : public T, public U
|
||||
{
|
||||
};
|
||||
|
||||
template <int tag>
|
||||
struct GenScatterImpl;
|
||||
|
||||
// Specialization for a general typelist
|
||||
template <>
|
||||
struct GenScatterImpl<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <class T, class MetaFunctionWrapper>
|
||||
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
||||
{
|
||||
typedef
|
||||
InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
|
||||
MetaFunctionWrapper>, typename T::Tail>,
|
||||
GenScatterHierarchy<typename T::Tail,
|
||||
MetaFunctionWrapper>
|
||||
> type;
|
||||
typedef VC_InaccessibleBase<GenScatterHierarchy<typename T::Head, MetaFunctionWrapper>,typename T::Tail> LeftBase;
|
||||
typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase;
|
||||
};
|
||||
};
|
||||
|
||||
// Specialization for a typelist with only one element
|
||||
template <>
|
||||
struct GenScatterImpl<TL::Private::AtomList_ID>
|
||||
{
|
||||
template <class T, class MetaFunctionWrapper>
|
||||
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
||||
{
|
||||
// for the last Holder-class no dummy class is needed.
|
||||
typedef
|
||||
InheritFromTwo < GenScatterHierarchy<typename T::Head,
|
||||
MetaFunctionWrapper>,
|
||||
GenScatterHierarchy<NullType,
|
||||
MetaFunctionWrapper>
|
||||
> type;
|
||||
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
|
||||
typedef GenScatterHierarchy<NullType, MetaFunctionWrapper> RightBase;
|
||||
};
|
||||
};
|
||||
// Specialization for a single type
|
||||
template <>
|
||||
struct GenScatterImpl<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class AtomicType, class MetaFunctionWrapper>
|
||||
struct In
|
||||
{
|
||||
typedef typename
|
||||
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
|
||||
typedef type LeftBase;
|
||||
typedef EmptyType RightBase;
|
||||
//typedef AtomicType::THIS_SELECTED bla;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Specialization for NullType
|
||||
template <>
|
||||
struct GenScatterImpl<TL::Private::NullType_ID>
|
||||
{
|
||||
template <class NullTypeList, class MetaFunctionWrapper>
|
||||
struct In
|
||||
{
|
||||
typedef EmptyType type;
|
||||
typedef type LeftBase;
|
||||
typedef type RightBase;
|
||||
};
|
||||
};
|
||||
} // end namespace Private
|
||||
|
||||
template <class T, class Unit>
|
||||
class GenScatterHierarchy : public Private::GenScatterImpl
|
||||
<
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Select
|
||||
<
|
||||
TL::Private::IsTypelist<T>::value, T, void
|
||||
>::Result TList;
|
||||
|
||||
typedef typename Private::GenScatterImpl
|
||||
<
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::LeftBase LeftBase;
|
||||
typedef typename Private::GenScatterImpl
|
||||
<
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::RightBase RightBase;
|
||||
|
||||
template <typename U> struct Rebind
|
||||
{
|
||||
typedef ApplyInnerType<Unit, U>::type 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 TList, class UnitWrapper>
|
||||
typename ApplyInnerType<UnitWrapper, T>::type&
|
||||
Field(GenScatterHierarchy<TList, UnitWrapper>& obj,Type2Type<T>* = (Type2Type<T>*)0)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class T, class TList, class UnitWrapper>
|
||||
const typename ApplyInnerType<UnitWrapper, T>::type&
|
||||
Field(const GenScatterHierarchy<TList, UnitWrapper>& obj, Type2Type<T>* = (Type2Type<T>*)0)
|
||||
{
|
||||
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)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
struct TupleUnitWrapper
|
||||
{
|
||||
template <class T>
|
||||
struct In
|
||||
{
|
||||
typedef TupleUnit<T> type;
|
||||
};
|
||||
};
|
||||
}
|
||||
template <class TList>
|
||||
struct Tuple : public GenScatterHierarchy<TList, Private::TupleUnitWrapper>
|
||||
{
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// helper class template FieldHelper
|
||||
// See Field below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <unsigned int i>
|
||||
struct FieldHelper
|
||||
{
|
||||
template<class H, class Unit>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
|
||||
typedef typename ApplyInnerType<Unit, ElementType>::type UnitType;
|
||||
|
||||
enum { isConst = TypeTraits<H>::isConst };
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const typename H::RightBase,
|
||||
typename H::RightBase
|
||||
>
|
||||
::Result RightBase;
|
||||
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
IsEqualType<UnitType, TupleUnit<ElementType> >::value,
|
||||
ElementType,
|
||||
UnitType
|
||||
>
|
||||
::Result UnqualifiedResultType;
|
||||
|
||||
public:
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const UnqualifiedResultType,
|
||||
UnqualifiedResultType
|
||||
>
|
||||
::Result ResultType;
|
||||
|
||||
// Must be a template, don't know why.
|
||||
// If Do is not a template and H& is used as parameter
|
||||
// MSVC will give a linker error.
|
||||
template <class T>
|
||||
static ResultType& Do(H& obj, T*)
|
||||
{
|
||||
//typedef typename T::RightBase RightBase;
|
||||
//RightBase& rightBase = obj;
|
||||
RightBase& rightBase = obj;
|
||||
return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase, (int*)0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct FieldHelper<0>
|
||||
{
|
||||
template<class H, class Unit>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename H::TList::Head ElementType;
|
||||
typedef typename ApplyInnerType<Unit, ElementType>::type UnitType;
|
||||
|
||||
enum { isConst = TypeTraits<H>::isConst };
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const typename H::LeftBase,
|
||||
typename H::LeftBase
|
||||
>
|
||||
::Result LeftBase;
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
IsEqualType<UnitType, TupleUnit<ElementType> >::value,
|
||||
ElementType,
|
||||
UnitType
|
||||
>
|
||||
::Result UnqualifiedResultType;
|
||||
|
||||
public:
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const UnqualifiedResultType,
|
||||
UnqualifiedResultType
|
||||
>
|
||||
::Result ResultType;
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
static ResultType& Do(H& obj, T*)
|
||||
{
|
||||
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 TList, class UnitWrapper>
|
||||
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
|
||||
Field(GenScatterHierarchy<TList, UnitWrapper>& obj, Int2Type<i>)
|
||||
{
|
||||
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
|
||||
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
|
||||
}
|
||||
*/
|
||||
template <unsigned int i, class TList, class UnitWrapper>
|
||||
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
|
||||
Field(GenScatterHierarchy<TList, UnitWrapper>& obj, Int2Type<i>* = (Int2Type<i>*)0)
|
||||
{
|
||||
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
|
||||
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenLinearHierarchy
|
||||
// Generates a linear hierarchy starting from a typelist and a template
|
||||
// Invocation (TList is a typelist, Model is a template of two args):
|
||||
// GenScatterHierarchy<TList, Model>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// VC 6.0 changes:
|
||||
// see GenScatterHierarchy
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
class Unit,
|
||||
class Root = EmptyType
|
||||
>
|
||||
class GenLinearHierarchy;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
|
||||
template <typename TListTag>
|
||||
struct GenLinearHierarchyHelper
|
||||
{
|
||||
template<class TList, class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenLinearHierarchyHelper<TL::Private::Typelist_tag>
|
||||
{
|
||||
template<class TList, class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
public:
|
||||
typedef typename
|
||||
ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenLinearHierarchyHelper<TL::Private::NullType_tag>
|
||||
{
|
||||
template<class TList, class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TList::Head Head;
|
||||
|
||||
public:
|
||||
typedef typename ApplyInnerType2<Unit,Head, Root>::type Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T, class U, class Root>
|
||||
struct Wrap
|
||||
{
|
||||
struct Dummy {};
|
||||
typedef typename T::Tail Tail;
|
||||
|
||||
// create the hierarchy
|
||||
typedef typename Private::GenLinearHierarchyHelper
|
||||
<
|
||||
typename TL::Private::IsTypelist<Tail>::type_tag
|
||||
>
|
||||
::template In<T, U, Root>::Result TempType;
|
||||
|
||||
typedef Private::VC_Base_Workaround<TempType, Dummy> type;
|
||||
|
||||
// this is nothing more than a typedef to the created hierarchy (TempType).
|
||||
// But if we try to inherit directly from TempType VC 6.0
|
||||
// will produce a "Error C2516. : is not a legal base class."
|
||||
typedef typename type::LeftBase Base;
|
||||
};
|
||||
} // namespace Private
|
||||
|
||||
// Trying to inherit from LinBase will result in "Error C2516. : is not a legal base class."
|
||||
// Private::Wrap introduces some levels of indirections which will
|
||||
// make the vc happy.
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
class Unit,
|
||||
class Root
|
||||
>
|
||||
class GenLinearHierarchy : public Private::Wrap<TList, Unit, Root>::Base
|
||||
{
|
||||
ASSERT_TYPELIST(TList); // TList must not be NullType
|
||||
|
||||
public:
|
||||
typedef typename Private::GenLinearHierarchyHelper
|
||||
<
|
||||
typename TL::Private::IsTypelist<typename TList::Tail>::type_tag
|
||||
>
|
||||
::template In<TList, Unit, Root>::Result LinBase;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#if defined (_MSC_VER) && _MSC_VER <= 1300
|
||||
#define FIELD(Obj, Nr) \
|
||||
Field(Obj, (Int2Type<Nr>*)0)
|
||||
#else
|
||||
#define FIELD(Obj, Nr) \
|
||||
Field<Nr>(Obj)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
|
||||
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6
|
||||
// Dec 08, 2002: Fixed problems with MSVC6-Version of GenScatterHierarchy when
|
||||
// used with typelists containing equal types. B.K.
|
||||
// New Version is ugly :-(
|
||||
// Dec 08, 2002: Interface changed for Field-Function. The old version does not
|
||||
// work correctly due to the "Explicitly Specified Template
|
||||
// Functions Not Overloaded Correctly"-Bug
|
||||
// (Microsoft KB Article - 240871). B.K.
|
||||
// Mar 08, 2003: New transparent workaround for Field-Functions. The FIELD-Macro
|
||||
// is no longer needed. B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#undef IS_TYPELIST
|
||||
#endif // HIERARCHYGENERATORS_INC_
|
106
include/noncc/MSVC/1200/LokiTypeInfo.h
Executable file
106
include/noncc/MSVC/1200/LokiTypeInfo.h
Executable file
|
@ -0,0 +1,106 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef LOKITYPEINFO_INC_
|
||||
#define LOKITYPEINFO_INC_
|
||||
|
||||
#include <typeinfo>
|
||||
#include <cassert>
|
||||
#include "Typelist.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class TypeInfo
|
||||
// Purpose: offer a first-class, comparable wrapper over std::type_info
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TypeInfo
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
TypeInfo(); // needed for containers
|
||||
TypeInfo(const std::type_info&); // non-explicit
|
||||
|
||||
// Access for the wrapped std::type_info
|
||||
const std::type_info& Get() const;
|
||||
// Compatibility functions
|
||||
bool before(const TypeInfo& rhs) const;
|
||||
const char* name() const;
|
||||
|
||||
private:
|
||||
const std::type_info* pInfo_;
|
||||
};
|
||||
|
||||
// Implementation
|
||||
|
||||
inline TypeInfo::TypeInfo()
|
||||
{
|
||||
class Nil {};
|
||||
pInfo_ = &typeid(Nil);
|
||||
assert(pInfo_);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(const std::type_info& ti)
|
||||
: pInfo_(&ti)
|
||||
{ assert(pInfo_); }
|
||||
|
||||
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return pInfo_->before(*rhs.pInfo_) != 0;
|
||||
}
|
||||
|
||||
inline const std::type_info& TypeInfo::Get() const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return *pInfo_;
|
||||
}
|
||||
|
||||
inline const char* TypeInfo::name() const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return pInfo_->name();
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
|
||||
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return (lhs.Get() == rhs.Get()) != 0; }
|
||||
|
||||
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return lhs.before(rhs); }
|
||||
|
||||
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs == rhs); }
|
||||
|
||||
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return rhs < lhs; }
|
||||
|
||||
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs > rhs); }
|
||||
|
||||
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs < rhs); }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // LOKITYPEINFO_INC_
|
177
include/noncc/MSVC/1200/MSVC6Helpers.h
Executable file
177
include/noncc/MSVC/1200/MSVC6Helpers.h
Executable file
|
@ -0,0 +1,177 @@
|
|||
// Last update: Mar 06, 2003
|
||||
// Added VoidWrap
|
||||
// Added qualification ::Loki::Private:: to types from the Private-Namespace
|
||||
// Thanks to Adi Shavit
|
||||
|
||||
#ifndef MSVC6HELPERS__H
|
||||
#define MSVC6HELPERS__H
|
||||
#if !defined (_MSC_VER) || _MSC_VER >= 1300
|
||||
#error "please use this header only with MSVC 6.0"
|
||||
#endif
|
||||
#include "TypeManip.h"
|
||||
namespace Loki
|
||||
{
|
||||
namespace Private
|
||||
{
|
||||
template <class T, class U>
|
||||
struct VC_InaccessibleBase : public T
|
||||
{};
|
||||
|
||||
// workaround for the "Error C2516. : is not a legal base class"
|
||||
// Use VC_Base_Workaround's LeftBase instead of the
|
||||
// alleged illegal base class.
|
||||
template <class T, class U>
|
||||
struct VC_Base_Workaround : public T, public U
|
||||
{
|
||||
typedef T LeftBase;
|
||||
};
|
||||
|
||||
// MSVC 6.0 does not allow the return of
|
||||
// expressions of type "cv void" in a functions with a return
|
||||
// type of cv void (6.6.3).
|
||||
// Functor.h uses this Type as a workaround.
|
||||
struct VoidAsType {};
|
||||
|
||||
// workaround for error C2182: '__formal' illegal use of type 'void'
|
||||
// when trying to use void as default value of a template parameter.
|
||||
// Instead of template<class T = void> class bla {};
|
||||
// simply write template <class T = VoidWrap::type> class bla {};
|
||||
// and the VC 6.0 will be happy.
|
||||
struct VoidWrap
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
// workarounds for template template parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AlwaysFalse
|
||||
// Invocation: AlwaysFalse<T>::value
|
||||
// value will always by 0 (false)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template< typename T >
|
||||
struct AlwaysFalse
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ApplyImpl1
|
||||
// Invocation: ApplyImpl1<T>::template Result<T1>
|
||||
// T must be a nontemplate type with a nested class template named In.
|
||||
// The class template is a helper for the Apply1-Template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class TypeWithNestedTemplate>
|
||||
struct ApplyImpl1
|
||||
{
|
||||
template<bool flag>
|
||||
struct VC_WORKAROUND : public TypeWithNestedTemplate {};
|
||||
|
||||
struct VC_WORKAROUND<true>
|
||||
{ template<class> struct In; };
|
||||
|
||||
template< typename T1 > struct Result : public
|
||||
VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1>
|
||||
{
|
||||
typedef VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base;
|
||||
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ApplyImpl2
|
||||
// Invocation: ApplyImpl2<T>::template Result<T1, T2>
|
||||
// T must be a nontemplate type with a nested class template named In.
|
||||
// The class template is a helper for the Apply2-Template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class TypeWithNestedTemplate>
|
||||
struct ApplyImpl2
|
||||
{
|
||||
template<bool flag>
|
||||
struct VC_WORKAROUND : public TypeWithNestedTemplate {};
|
||||
|
||||
struct VC_WORKAROUND<true>
|
||||
{template<class T, class U> struct In; };
|
||||
|
||||
template< typename T1, typename T2 > struct Result : public
|
||||
VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
} // end of namespace Private
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Apply1
|
||||
// Invocation: Apply1<T, U>
|
||||
// Applies the type U to the inner template In of type T
|
||||
// The class template Apply1 helps to emulate template template parameters
|
||||
// i first saw this technique in boost's mpl library.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename F, typename T1>
|
||||
struct Apply1 : ::Loki::Private::ApplyImpl1<F>::template Result<T1>
|
||||
{
|
||||
typedef typename ::Loki::Private::ApplyImpl1<F>::template Result<T1>::Base Base;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Apply2
|
||||
// Invocation: Apply2<T, U, V>
|
||||
// Applies the types U and V to the inner template In of type T
|
||||
// The class template Apply2 helps to emulate template template parameters
|
||||
// i first saw this technique in boost's mpl library.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename F, typename T1, typename T2>
|
||||
struct Apply2 : ::Loki::Private::ApplyImpl2<F>::template Result<T1, T2>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ApplyInnerType
|
||||
// Invocation: ApplyInnerType<Wrapper, U>::type
|
||||
// Applies the type U to the the inner template 'In' of type Wrapper and typedefs
|
||||
// the resulting type to 'type'
|
||||
// The class template ApplyInnerType helps to emulate template template parameters
|
||||
// i first saw this technique in boost's mpl library.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class Wrapper, class T>
|
||||
struct ApplyInnerType
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class X> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ApplyInnerType2
|
||||
// Invocation: ApplyInnerType2<Wrapper, U, V>::type
|
||||
// Applies the types U and V to the the inner template 'In' of type Wrapper and typedefs
|
||||
// the resulting type to 'type'
|
||||
// The class template ApplyInnerType helps to emulate template template parameters
|
||||
// i first saw this technique in boost's mpl library.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class Wrapper, class T, class V>
|
||||
struct ApplyInnerType2
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class X, class Y> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
|
||||
};
|
||||
|
||||
template <class Wrapper, class T, class U, class V, class W>
|
||||
struct ApplyInnerType4
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class W, class X, class Y, class Z> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
848
include/noncc/MSVC/1200/MultiMethods.h
Executable file
848
include/noncc/MSVC/1200/MultiMethods.h
Executable file
|
@ -0,0 +1,848 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Mar 21, 2003
|
||||
// Added a new explicit template argument specification workaround for
|
||||
// FnDispatcher::Add which is more compliant with other
|
||||
// explicit template argument specification workarounds used in this port.
|
||||
//
|
||||
// Example usage:
|
||||
// --------------
|
||||
// Using the original library one writes:
|
||||
// typedef FnDispatcher<Shape> Dispatcher;
|
||||
// void Hatch(Rectangle& lhs, Poly& rhs) {...}
|
||||
//
|
||||
// Dispatcher dis;
|
||||
// disp.Add<Rectangle, Poly, &Hatch>();
|
||||
//
|
||||
// Using this port the example either becomes:
|
||||
// dis.Add(Dispatcher::Add<Rectangle, Poly, &Hatch>());
|
||||
// or alternatively
|
||||
// Dispatcher::AddI<Rectangle, Poly, &Hatch>()(dis);
|
||||
//
|
||||
// All dispatchers now have void as default value for return types.
|
||||
// All dispatchers now support void as return type.
|
||||
//
|
||||
//
|
||||
// The port now uses Tye2Type-parameters instead of plain pointers as
|
||||
// a workaround of VC's explicit template argument specification bug.
|
||||
//
|
||||
// For example:
|
||||
// The original declaration of BasicDispatcher::Add looks like this:
|
||||
//
|
||||
// template <class SomeLhs, class SomeRhs>
|
||||
// void Add(CallbackType fun);
|
||||
//
|
||||
// and you call it like this:
|
||||
// obj.Add<Type1, Type2>(yourFun);
|
||||
//
|
||||
// This port uses:
|
||||
//
|
||||
// template <class SomeLhs, class SomeRhs>
|
||||
// void Add(CallbackType fun, Type2Type<SomeLhs>, Type2Type<SomeRhs>);
|
||||
//
|
||||
// and you call it like this:
|
||||
// obj.Add(yourFun, Type2Type<Type1>(), Type2Type<Type2>());
|
||||
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation helpers for StaticDispatcher
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
|
||||
struct InvocationTraitsBase
|
||||
{
|
||||
protected:
|
||||
template <class R>
|
||||
struct BaseImpl
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct BaseImpl<void>
|
||||
{
|
||||
static ResultType
|
||||
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
|
||||
{
|
||||
exec.Fire(lhs, rhs);
|
||||
}
|
||||
static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs,
|
||||
Executor& exec, Int2Type<true>)
|
||||
{
|
||||
exec.Fire(rhs, lhs);
|
||||
}
|
||||
};
|
||||
public:
|
||||
typedef BaseImpl<ResultType> Base;
|
||||
};
|
||||
template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
|
||||
struct InvocationTraits : public InvocationTraitsBase
|
||||
<SomeLhs, SomeRhs, Executor, ResultType>::Base
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
template<class Executor, class BaseLhs, class TypesLhs, bool symmetric,
|
||||
class BaseRhs, class TypesRhs, typename ResultType>
|
||||
class StaticDispatcherBase
|
||||
{
|
||||
private:
|
||||
// Base for ResultType != void
|
||||
template <class R>
|
||||
class In
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
protected:
|
||||
~In() {}
|
||||
public:
|
||||
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec)
|
||||
{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
|
||||
}; // In<R>
|
||||
|
||||
// Base for ResultType == void
|
||||
template <>
|
||||
class In<void>
|
||||
{
|
||||
template <class SomeLhs>
|
||||
static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, NullType)
|
||||
{ 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, void> CallTraits;
|
||||
|
||||
CallTraits::DoDispatch(lhs, *p2, exec, i2t);
|
||||
return;
|
||||
}
|
||||
DispatchRhs(lhs, rhs, exec, Tail());
|
||||
}
|
||||
|
||||
static ResultType DispatchLhs( BaseLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, NullType)
|
||||
{ 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))
|
||||
{
|
||||
DispatchRhs(*p1, rhs, exec, TypesRhs());
|
||||
return;
|
||||
}
|
||||
DispatchLhs(lhs, rhs, exec, Tail());
|
||||
}
|
||||
|
||||
protected:
|
||||
~In<void>() {}
|
||||
public:
|
||||
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec)
|
||||
{ DispatchLhs(lhs, rhs, exec, TypesLhs()); }
|
||||
}; // In<void>
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
}; // StaticDispatcherBase
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 = Loki::Private::VoidWrap::type
|
||||
>
|
||||
class StaticDispatcher : public ::Loki::Private::StaticDispatcherBase
|
||||
<
|
||||
Executor, BaseLhs, TypesLhs, symmetric,
|
||||
BaseRhs, TypesRhs, ResultType
|
||||
>::Base
|
||||
{
|
||||
|
||||
public:
|
||||
// member functions moved to base class
|
||||
// static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
|
||||
// Executor exec)
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation helpers for BasicDispatcher
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
template <class BaseLhs, class BaseRhs, typename ResultType,
|
||||
typename CallbackType>
|
||||
class BasicDispatcherBase
|
||||
{
|
||||
private:
|
||||
// Common (independent of the result type) code for BasicDispatcher
|
||||
class Common
|
||||
{
|
||||
private:
|
||||
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
|
||||
{
|
||||
callbackMap_[KeyType(lhs, rhs)] = fun;
|
||||
}
|
||||
bool DoRemove(TypeInfo lhs, TypeInfo rhs)
|
||||
{
|
||||
return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
|
||||
}
|
||||
protected:
|
||||
typedef std::pair<TypeInfo,TypeInfo> KeyType;
|
||||
typedef CallbackType MappedType;
|
||||
typedef AssocVector<KeyType, MappedType> MapType;
|
||||
MapType callbackMap_;
|
||||
~Common() {}
|
||||
public:
|
||||
template <class SomeLhs, class SomeRhs>
|
||||
void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>,
|
||||
::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
|
||||
}
|
||||
|
||||
|
||||
template <class SomeLhs, class SomeRhs>
|
||||
bool Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
|
||||
}
|
||||
}; // Common
|
||||
template <class R> // Base for ResultType != void
|
||||
class In : public Common
|
||||
{
|
||||
public:
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
typename MapType::key_type k(typeid(lhs),typeid(rhs));
|
||||
typename MapType::iterator i = Common::callbackMap_.find(k);
|
||||
if (i == Common::callbackMap_.end())
|
||||
{
|
||||
throw std::runtime_error("Function not found");
|
||||
}
|
||||
return (i->second)(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
~In() {}
|
||||
}; // In
|
||||
template <> // Base for ResultType == void
|
||||
class In<void> : public Common
|
||||
{
|
||||
public:
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
typename MapType::key_type k(typeid(lhs),typeid(rhs));
|
||||
typename MapType::iterator i = Common::callbackMap_.find(k);
|
||||
if (i == Common::callbackMap_.end())
|
||||
{
|
||||
throw std::runtime_error("Function not found");
|
||||
}
|
||||
(i->second)(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
~In<void>() {}
|
||||
}; // In
|
||||
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
}; // BasicDispatcherBase
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 = Loki::Private::VoidWrap::type,
|
||||
typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
|
||||
>
|
||||
class BasicDispatcher : public ::Loki::Private::BasicDispatcherBase
|
||||
<
|
||||
BaseLhs, BaseRhs, ResultType, CallbackType
|
||||
>::Base
|
||||
{
|
||||
public:
|
||||
// member functions moved to base class
|
||||
// template <class SomeLhs, class SomeRhs>
|
||||
// void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>,
|
||||
// ::Loki::Type2Type<SomeRhs>)
|
||||
//
|
||||
// template <class SomeLhs, class SomeRhs>
|
||||
// bool Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
|
||||
//
|
||||
// ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
|
||||
};
|
||||
|
||||
|
||||
struct BasicDispatcherWrapper
|
||||
{
|
||||
template <class T, class U, class V, class W>
|
||||
struct In
|
||||
{
|
||||
typedef BasicDispatcher<T, U, V, W> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
struct StaticCasterWrapper
|
||||
{
|
||||
template <class T, class U>
|
||||
struct In
|
||||
{
|
||||
typedef StaticCaster<T, U> type;
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
struct DynamicCasterWrapper
|
||||
{
|
||||
template <class T, class U>
|
||||
struct In
|
||||
{
|
||||
typedef DynamicCaster<T, U> type;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Private::FnDispatcherHelper
|
||||
// Implements trampolines and argument swapping used by FnDispatcher
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
template <class BaseLhs, class BaseRhs, typename ResultType,
|
||||
class DispatcherBackend>
|
||||
class FnDispatcherBase
|
||||
{
|
||||
private:
|
||||
// Implementation for ResultType != void
|
||||
template <class R>
|
||||
class In
|
||||
{
|
||||
public:
|
||||
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
|
||||
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
|
||||
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
return backEnd_.Go(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
~In() {}
|
||||
}; // In
|
||||
// Implementation for ResultType == void
|
||||
template <>
|
||||
class In<void>
|
||||
{
|
||||
public:
|
||||
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
|
||||
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
|
||||
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
backEnd_.Go(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
~In<void>() {}
|
||||
}; // In<void>
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
}; // FnDispatcherBase
|
||||
|
||||
template< class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
|
||||
class ResultType, class CastLhs, class CastRhs,
|
||||
void (*Callback)(SomeLhs&, SomeRhs&)>
|
||||
class FnDispatcherHelperBase
|
||||
{
|
||||
private:
|
||||
template <class R>
|
||||
class In
|
||||
{
|
||||
public:
|
||||
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);
|
||||
}
|
||||
protected:
|
||||
~In() {}
|
||||
};
|
||||
template <>
|
||||
class In<void>
|
||||
{
|
||||
public:
|
||||
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||
}
|
||||
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
|
||||
{
|
||||
Trampoline(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
~In<void>() {}
|
||||
};
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
|
||||
typename ResultType, class CastLhs, class CastRhs,
|
||||
ResultType (*Callback)(SomeLhs&, SomeRhs&)
|
||||
>
|
||||
struct FnDispatcherHelper : public FnDispatcherHelperBase
|
||||
<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
|
||||
ResultType, CastLhs, CastRhs, Callback
|
||||
>::Base
|
||||
{};
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template FnDispatcher
|
||||
// Implements an automatic logarithmic double dispatcher for functions
|
||||
// Features automated conversions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class BaseLhs, class BaseRhs = BaseLhs,
|
||||
typename ResultType = Loki::Private::VoidWrap::type,
|
||||
class CastingPolicy = DynamicCasterWrapper,
|
||||
class DispatcherBackend = BasicDispatcherWrapper>
|
||||
class FnDispatcher : public ::Loki::Private::FnDispatcherBase
|
||||
<
|
||||
BaseLhs, BaseRhs,
|
||||
ResultType, DispatcherBackend
|
||||
>::Base
|
||||
|
||||
{
|
||||
typedef typename ::Loki::Private::FnDispatcherBase
|
||||
<
|
||||
BaseLhs, BaseRhs, ResultType, DispatcherBackend
|
||||
>::Base Base;
|
||||
public:
|
||||
template <class SomeLhs, class SomeRhs>
|
||||
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&),
|
||||
::Loki::Type2Type<SomeLhs>,
|
||||
::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
Base::backEnd_.Add(pFun, ::Loki::Type2Type<SomeLhs>(),
|
||||
::Loki::Type2Type<SomeRhs>());
|
||||
}
|
||||
|
||||
|
||||
// two different workarounds for FnDispatcher::Add
|
||||
// Using the first one writes:
|
||||
// DisType dispatcher;
|
||||
// dispatcher.Add(DisType::Etas<SomeLhs, SomeRhs, &AFunc>());
|
||||
// using the second workaround the call becomes:
|
||||
// DisType dispatcher;
|
||||
// DisTyp::AddI<SomeLhs, SomeRhs, &AFunc>()(dispatcher);
|
||||
|
||||
// Helper-class for the first workaround.
|
||||
// When calling FnDispatcher::Add provide an object of this type
|
||||
// as argument.
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false>
|
||||
struct Etas
|
||||
{
|
||||
typedef Private::FnDispatcherHelper<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,
|
||||
ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
|
||||
ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
|
||||
callback> Local;
|
||||
enum {sym = symmetric};
|
||||
typedef SomeLhs Lhs;
|
||||
typedef SomeRhs Rhs;
|
||||
};
|
||||
|
||||
// EtasType has to be a template parameter. If one tries to use
|
||||
// a parameter of type Etas the MSVC 6.0 won't generate correct
|
||||
// code.
|
||||
template <class EtasType>
|
||||
void Add(EtasType EtasObj)
|
||||
{
|
||||
typedef typename EtasType::Local Local;
|
||||
typedef typename EtasType::Lhs SomeLhs;
|
||||
typedef typename EtasType::Rhs SomeRhs;
|
||||
|
||||
Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
|
||||
::Loki::Type2Type<SomeRhs>());
|
||||
if (EtasType::sym)
|
||||
{
|
||||
Add(&Local::TrampolineR, ::Loki::Type2Type<SomeRhs>(),
|
||||
::Loki::Type2Type<SomeLhs>());
|
||||
}
|
||||
}
|
||||
|
||||
// alternative workaround for FnDispatcher::Add
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false>
|
||||
struct AddI
|
||||
{
|
||||
void operator()(FnDispatcher<BaseLhs, BaseRhs, ResultType,
|
||||
CastingPolicy,DispatcherBackend>& f)
|
||||
{
|
||||
typedef Private::FnDispatcherHelper<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,
|
||||
ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
|
||||
ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
|
||||
callback> Local;
|
||||
f.Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
|
||||
::Loki::Type2Type<SomeRhs>());
|
||||
if (symmetric)
|
||||
{
|
||||
f.Add(&Local::TrampolineR, ::Loki::Type2Type<SomeRhs>(),
|
||||
::Loki::Type2Type<SomeLhs>());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class SomeLhs, class SomeRhs>
|
||||
void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
Base::backEnd_.Remove(::Loki::Type2Type<SomeLhs>(),
|
||||
::Loki::Type2Type<SomeRhs>());
|
||||
}
|
||||
|
||||
|
||||
// moved to base class
|
||||
// ResultType Go(BaseLhs& lhs, BaseRhs& 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 FunctorDispatcherHelperBase
|
||||
{
|
||||
template <class R>
|
||||
class In
|
||||
{
|
||||
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:
|
||||
In(const Fun& fun) : fun_(fun) {}
|
||||
|
||||
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
return Fire(lhs,rhs,Int2Type<SwapArgs>());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class In<void>
|
||||
{
|
||||
Fun fun_;
|
||||
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
|
||||
{
|
||||
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||
}
|
||||
ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
|
||||
{
|
||||
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
||||
}
|
||||
public:
|
||||
In<void>(const Fun& fun) : fun_(fun) {}
|
||||
|
||||
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
Fire(lhs,rhs,Int2Type<SwapArgs>());
|
||||
}
|
||||
};
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
}; // FunctorDispatcherHelperBase
|
||||
|
||||
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
|
||||
typename ResultType, class CastLhs, class CastRhs, class Fun, bool SwapArgs>
|
||||
class FunctorDispatcherHelper : public FunctorDispatcherHelperBase
|
||||
<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
|
||||
ResultType, CastLhs, CastRhs, Fun,
|
||||
SwapArgs
|
||||
>::Base
|
||||
{
|
||||
private:
|
||||
typedef typename FunctorDispatcherHelperBase
|
||||
<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
|
||||
ResultType, CastLhs, CastRhs, Fun, SwapArgs
|
||||
>::Base Base;
|
||||
public:
|
||||
FunctorDispatcherHelper(const Fun& f) : Base(f)
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename ResultType, class BaseLhs, class BaseRhs,
|
||||
class DispatcherBackend>
|
||||
class FunctorDispatcherBase
|
||||
{
|
||||
private:
|
||||
class Common
|
||||
{
|
||||
protected:
|
||||
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
|
||||
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
|
||||
|
||||
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType,
|
||||
FunctorType>::type backEnd_;
|
||||
~Common() {}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class In : public Common
|
||||
{
|
||||
public:
|
||||
typedef typename Common::ArgsList ArgsList;
|
||||
typedef typename Common::FunctorType FunctorType;
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
return Common::backEnd_.Go(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
In() {}
|
||||
};
|
||||
template <>
|
||||
class In<void> : public Common
|
||||
{
|
||||
public:
|
||||
typedef typename Common::ArgsList ArgsList;
|
||||
typedef typename Common::FunctorType FunctorType;
|
||||
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
|
||||
{
|
||||
Common::backEnd_.Go(lhs, rhs);
|
||||
}
|
||||
protected:
|
||||
In<void>() {}
|
||||
};
|
||||
public:
|
||||
typedef In<ResultType> Base;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template FunctorDispatcher
|
||||
// Implements a logarithmic double dispatcher for functors
|
||||
// Features automated casting
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class BaseLhs, class BaseRhs = BaseLhs,
|
||||
typename ResultType = Loki::Private::VoidWrap::type,
|
||||
class CastingPolicy = DynamicCasterWrapper,
|
||||
class DispatcherBackend = BasicDispatcherWrapper>
|
||||
class FunctorDispatcher : public ::Loki::Private::FunctorDispatcherBase
|
||||
<
|
||||
ResultType, BaseLhs, BaseRhs, DispatcherBackend
|
||||
>::Base
|
||||
{
|
||||
typedef typename ::Loki::Private::FunctorDispatcherBase
|
||||
<
|
||||
ResultType, BaseLhs, BaseRhs, DispatcherBackend
|
||||
>::Base Base;
|
||||
public:
|
||||
typedef Base::ArgsList ArgsList;
|
||||
typedef Base::FunctorType FunctorType;
|
||||
template <class SomeLhs, class SomeRhs, class Fun>
|
||||
void Add(const Fun& fun, ::Loki::Type2Type<SomeLhs>,
|
||||
::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
|
||||
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseRhs>::type CastTwo;
|
||||
typedef typename
|
||||
Private::FunctorDispatcherHelper
|
||||
<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
|
||||
ResultType,CastOne,CastTwo,Fun, false
|
||||
>::Base Adapter;
|
||||
Base::backEnd_.Add(FunctorType(Adapter(fun), Loki::Disambiguate()),
|
||||
Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
|
||||
}
|
||||
template <class SomeLhs, class SomeRhs, class Fun>
|
||||
void Add(const Fun& fun, ::Loki::Type2Type<SomeLhs>,
|
||||
::Loki::Type2Type<SomeRhs>, bool symmetric)
|
||||
{
|
||||
Add(fun, Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
|
||||
|
||||
if (symmetric)
|
||||
{
|
||||
// Note: symmetry only makes sense where BaseLhs==BaseRhs
|
||||
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
|
||||
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type CastTwo;
|
||||
typedef typename
|
||||
Private::FunctorDispatcherHelper
|
||||
<
|
||||
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
|
||||
ResultType,CastOne,CastTwo,Fun, true
|
||||
>::Base AdapterR;
|
||||
|
||||
Base::backEnd_.Add(FunctorType(AdapterR(fun), Loki::Disambiguate()),
|
||||
Type2Type<SomeRhs>(), Type2Type<SomeLhs>());
|
||||
}
|
||||
}
|
||||
|
||||
template <class SomeLhs, class SomeRhs>
|
||||
void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
|
||||
{
|
||||
Base::backEnd_.Remove(Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
|
||||
}
|
||||
|
||||
// moved to base class
|
||||
// ResultType Go(BaseLhs& lhs, BaseRhs& 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)
|
||||
// Oct 28, 2002: ported by Benjamin Kaufmann to MSVC 6
|
||||
// Feb 19, 2003: replaced pointer-Dummies with Type2Type-Parameters and added
|
||||
// support for return type void. B.K.
|
||||
// Mar 06, 2003: Changed default values for return types to void.
|
||||
// Added protected destructors to private implementation classes B.K.
|
||||
// Mar 20. 2003: Fixed Bugs in FnDispatcherHelperBase, FnDispatcher::Add and
|
||||
// FunctorDispatcher::Add.
|
||||
// New Interface for FnDispatcher::Add.B.K.
|
||||
// Mar 21, 2003: Added new explicit template argument specification workaround
|
||||
// for FnDispatcher::Add B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
37
include/noncc/MSVC/1200/NullType.h
Executable file
37
include/noncc/MSVC/1200/NullType.h
Executable 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 NULLTYPE_INC_
|
||||
#define NULLTYPE_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class NullType
|
||||
// Used as a placeholder for "no type here"
|
||||
// Useful as an end marker in typelists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NullType {};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // NULLTYPE_INC_
|
49
include/noncc/MSVC/1200/Singleton.cpp
Executable file
49
include/noncc/MSVC/1200/Singleton.cpp
Executable file
|
@ -0,0 +1,49 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Oct 06, 2002
|
||||
|
||||
#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>(VC_BROKEN_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!!!
|
||||
// Oct 06 2002: ported by Benjamin Kaufmann to VC 6.0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
498
include/noncc/MSVC/1200/Singleton.h
Executable file
498
include/noncc/MSVC/1200/Singleton.h
Executable file
|
@ -0,0 +1,498 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Feb 24, 2003
|
||||
|
||||
#ifndef SINGLETON_INC_
|
||||
#define SINGLETON_INC_
|
||||
|
||||
#include "Threads.h"
|
||||
#include "MSVC6Helpers.h" // for apply-template
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
#if _MSC_VER <= 1200
|
||||
#define VC_BROKEN_STD
|
||||
#else
|
||||
#define VC_BROKEN_STD std
|
||||
#endif
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
namespace Private
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class LifetimeTracker
|
||||
// Helper class for SetLongevity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LifetimeTracker
|
||||
{
|
||||
public:
|
||||
LifetimeTracker(unsigned int x) : longevity_(x)
|
||||
{}
|
||||
|
||||
virtual ~LifetimeTracker() = 0;
|
||||
|
||||
static bool Compare(const LifetimeTracker* lhs,
|
||||
const LifetimeTracker* rhs)
|
||||
{
|
||||
return rhs->longevity_ > lhs->longevity_;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int longevity_;
|
||||
};
|
||||
|
||||
// Definition required
|
||||
inline LifetimeTracker::~LifetimeTracker() {}
|
||||
|
||||
// Helper data
|
||||
typedef LifetimeTracker** TrackerArray;
|
||||
extern TrackerArray pTrackerArray;
|
||||
extern unsigned int elements;
|
||||
|
||||
// Helper destroyer function
|
||||
template <typename T>
|
||||
struct Deleter
|
||||
{
|
||||
static void Delete(T* pObj)
|
||||
{ delete pObj; }
|
||||
};
|
||||
|
||||
// Concrete lifetime tracker for objects of type T
|
||||
template <typename T, typename Destroyer>
|
||||
class ConcreteLifetimeTracker : public LifetimeTracker
|
||||
{
|
||||
public:
|
||||
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
|
||||
: LifetimeTracker(longevity)
|
||||
, pTracked_(p)
|
||||
, destroyer_(d)
|
||||
{}
|
||||
|
||||
~ConcreteLifetimeTracker()
|
||||
{ destroyer_(pTracked_); }
|
||||
|
||||
private:
|
||||
T* pTracked_;
|
||||
Destroyer destroyer_;
|
||||
};
|
||||
|
||||
void AtExitFn(); // declaration needed below
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template SetLongevity
|
||||
// Assigns an object a longevity; ensures ordered destructions of objects
|
||||
// registered thusly during the exit sequence of the application
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename Destroyer>
|
||||
void SetLongevity(T* pDynObject, unsigned int longevity,
|
||||
Destroyer d = Private::Deleter<T>::Delete)
|
||||
{
|
||||
using namespace Private;
|
||||
|
||||
TrackerArray pNewArray = static_cast<TrackerArray>(
|
||||
VC_BROKEN_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
|
||||
VC_BROKEN_STD::atexit(Private::AtExitFn);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CreateUsingNew
|
||||
// Implementation of the CreationPolicy used by SingletonHolder
|
||||
// Creates objects using a straight call to the new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CreateUsingNew
|
||||
{
|
||||
template <class T>
|
||||
static T* Create(const volatile T* p = 0)
|
||||
{
|
||||
return new T;
|
||||
}
|
||||
template <class T>
|
||||
static void Destroy(T* p)
|
||||
{ delete p; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CreateUsingNew
|
||||
// Implementation of the CreationPolicy used by SingletonHolder
|
||||
// Creates objects using a call to std::malloc, followed by a call to the
|
||||
// placement new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CreateUsingMalloc
|
||||
{
|
||||
template <class T>
|
||||
static T* Create(const volatile T* dummy = 0)
|
||||
{
|
||||
void* p = VC_BROKEN_STD::malloc(sizeof(T));
|
||||
if (!p) return 0;
|
||||
return new(p) T;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void Destroy(T* p)
|
||||
{
|
||||
p->~T();
|
||||
VC_BROKEN_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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CreateStatic
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
// alignment of a member was sensitive to packing
|
||||
#pragma warning( disable : 4121 )
|
||||
#endif // _MSC_VER
|
||||
template <class T>
|
||||
union MaxAlign
|
||||
{
|
||||
char t_[sizeof(T)];
|
||||
short int shortInt_;
|
||||
int int_;
|
||||
long int longInt_;
|
||||
float float_;
|
||||
double double_;
|
||||
long double longDouble_;
|
||||
struct Test;
|
||||
int Test::* pMember_;
|
||||
int (Test::*pMemberFn_)(int);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif // _MSC_VER
|
||||
|
||||
template <class T>
|
||||
static T* Create(const volatile T* p = 0)
|
||||
{
|
||||
static MaxAlign<T> staticMemory_;
|
||||
return new(&staticMemory_) T;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void Destroy(T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultLifetime
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction as per C++ rules
|
||||
// Forwards to std::atexit
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
void Thrower(const char* s) {throw std::logic_error(s); }
|
||||
}
|
||||
|
||||
struct DefaultLifetime
|
||||
{
|
||||
template <class T>
|
||||
static void ScheduleDestruction(T*, void (*pFun)())
|
||||
{ VC_BROKEN_STD::atexit(pFun); }
|
||||
|
||||
template <class T>
|
||||
static void OnDeadReference(const volatile T* p = 0 )
|
||||
{
|
||||
// the throw will yield a C1001-internal compiler error.
|
||||
// The new level of indirection solves the problem
|
||||
// throw std::logic_error("Dead Reference Detected");
|
||||
Thrower("Dead Reference Detected");
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PhoenixSingleton
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction as per C++ rules, and it allows object
|
||||
// recreation by not throwing an exception from OnDeadReference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class PhoenixSingleton
|
||||
{
|
||||
private:
|
||||
template <class T>
|
||||
struct StaticData
|
||||
{
|
||||
static bool destroyedOnce_;
|
||||
};
|
||||
public:
|
||||
template <class T>
|
||||
static void ScheduleDestruction(T*, void (*pFun)())
|
||||
{
|
||||
|
||||
#ifndef ATEXIT_FIXED
|
||||
if (!StaticData<T>::destroyedOnce_)
|
||||
#endif
|
||||
VC_BROKEN_STD::atexit(pFun);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void OnDeadReference(const volatile T* p = 0 )
|
||||
{
|
||||
#ifndef ATEXIT_FIXED
|
||||
StaticData<T>::destroyedOnce_ = true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
#ifndef ATEXIT_FIXED
|
||||
template <class T>
|
||||
bool ::Loki::PhoenixSingleton::StaticData<T>::destroyedOnce_ = false;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Adapter
|
||||
// Helper for SingletonWithLongevity below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class T>
|
||||
struct Adapter
|
||||
{
|
||||
void operator()(T*) { pFun_(); return ; }
|
||||
void (*pFun_)();
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonWithLongevity
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction in order of their longevities
|
||||
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
|
||||
// object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SingletonWithLongevity
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
static void ScheduleDestruction(T* pObj, void (*pFun)())
|
||||
{
|
||||
Private::Adapter<T> adapter;
|
||||
adapter.pFun_ = pFun ;
|
||||
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void OnDeadReference(const volatile T* p = 0 )
|
||||
{
|
||||
// the throw will yield a C1001-internal compiler error.
|
||||
// The new level of indirection solves the problem
|
||||
// throw std::logic_error("Dead Reference Detected");
|
||||
Thrower("Dead Reference Detected");
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template NoDestroy
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Never destroys the object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct NoDestroy
|
||||
{
|
||||
template <class T>
|
||||
static void ScheduleDestruction(T*, void (*)())
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
static void OnDeadReference(const volatile T* p = 0)
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonHolder
|
||||
// Provides Singleton amenities for a type T
|
||||
// To protect that type from spurious instantiations, you have to protect it
|
||||
// yourself.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
class CreationPolicy = CreateUsingNew,
|
||||
class LifetimePolicy = DefaultLifetime,
|
||||
class ThreadingModel = SingleThreaded
|
||||
>
|
||||
class SingletonHolder
|
||||
{
|
||||
public:
|
||||
static T& Instance();
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
static void MakeInstance();
|
||||
static void DestroySingleton();
|
||||
|
||||
// Protection
|
||||
SingletonHolder();
|
||||
|
||||
// Data
|
||||
typedef typename Apply1<ThreadingModel, T*>::VolatileType VolatileType;
|
||||
static VolatileType pInstance_;
|
||||
static bool destroyed_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder's data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
class C,
|
||||
class L,
|
||||
class M
|
||||
>
|
||||
typename SingletonHolder<T, C, L, M>::VolatileType
|
||||
SingletonHolder<T, C, L, M>::pInstance_;
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
class C,
|
||||
class L,
|
||||
class M
|
||||
>
|
||||
bool SingletonHolder<T, C, L, M>::destroyed_;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder::Instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
class CreationPolicy,
|
||||
class LifetimePolicy,
|
||||
class ThreadingModel
|
||||
>
|
||||
inline T& SingletonHolder<T, CreationPolicy,
|
||||
LifetimePolicy, ThreadingModel>::Instance()
|
||||
{
|
||||
if (!pInstance_)
|
||||
{
|
||||
MakeInstance();
|
||||
}
|
||||
return *pInstance_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingletonHolder::MakeInstance (helper for Instance)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
class CreationPolicy,
|
||||
class LifetimePolicy,
|
||||
class ThreadingModel
|
||||
>
|
||||
void SingletonHolder<T, CreationPolicy,
|
||||
LifetimePolicy, ThreadingModel>::MakeInstance()
|
||||
{
|
||||
//typename Apply1<ThreadingModel, T>::Lock guard;
|
||||
typename Apply1<ThreadingModel, SingletonHolder>::Lock guard;
|
||||
(void)guard;
|
||||
|
||||
if (!pInstance_)
|
||||
{
|
||||
if (destroyed_)
|
||||
{
|
||||
LifetimePolicy::OnDeadReference(pInstance_);
|
||||
destroyed_ = false;
|
||||
}
|
||||
pInstance_ = CreationPolicy::Create(pInstance_);
|
||||
LifetimePolicy::ScheduleDestruction(pInstance_,
|
||||
&DestroySingleton);
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
class T,
|
||||
class CreationPolicy,
|
||||
class L,
|
||||
class M
|
||||
>
|
||||
void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
|
||||
{
|
||||
assert(!destroyed_);
|
||||
CreationPolicy::Destroy(pInstance_);
|
||||
pInstance_ = 0;
|
||||
destroyed_ = true;
|
||||
}
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Oct 06 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// Feb 24, 2003: changed parameter name of CreateUsingMalloc::Create,
|
||||
// changed SingletonHolder::MakeInstance in accordance with
|
||||
// Bug-report #691687 B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SINGLETON_INC_
|
420
include/noncc/MSVC/1200/SmallObj.cpp
Executable file
420
include/noncc/MSVC/1200/SmallObj.cpp
Executable file
|
@ -0,0 +1,420 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: March 20, 2001
|
||||
|
||||
#include "SmallObj.h"
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
using namespace Loki;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Init
|
||||
// Initializes a chunk object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Init(VC_BROKEN_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(VC_BROKEN_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(VC_BROKEN_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, VC_BROKEN_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(VC_BROKEN_STD::size_t blockSize)
|
||||
: blockSize_(blockSize)
|
||||
, allocChunk_(0)
|
||||
, deallocChunk_(0)
|
||||
{
|
||||
assert(blockSize_ > 0);
|
||||
|
||||
prev_ = next_ = this;
|
||||
|
||||
VC_BROKEN_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 VC_BROKEN_STD::size_t chunkLength = numBlocks_ * blockSize_;
|
||||
|
||||
Chunk* lo = deallocChunk_;
|
||||
Chunk* hi = deallocChunk_ + 1;
|
||||
Chunk* loBound = &chunks_.front();
|
||||
Chunk* hiBound = &chunks_.back() + 1;
|
||||
|
||||
// Special case: deallocChunk_ is the last in the array
|
||||
if (hi == hiBound) hi = 0;
|
||||
|
||||
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(
|
||||
VC_BROKEN_STD::size_t chunkSize,
|
||||
VC_BROKEN_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(VC_BROKEN_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, VC_BROKEN_STD::size_t numBytes)
|
||||
{
|
||||
if (numBytes > maxObjectSize_) {operator delete(p); return;}
|
||||
|
||||
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!!!
|
||||
// Aug 02, 2002: Fix in VicinityFind sent by Pavel Vozenilek
|
||||
// Oct 11, 2002: ported by Benjamin Kaufmann to VC 6.0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
196
include/noncc/MSVC/1200/SmallObj.h
Executable file
196
include/noncc/MSVC/1200/SmallObj.h
Executable file
|
@ -0,0 +1,196 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Jan 12, 2003
|
||||
// changed SmallObject's op new from
|
||||
// static void* operator new(VC_BROKEN_STD::size_t size);
|
||||
// to
|
||||
// static void* operator new(VC_BROKEN_STD::size_t size,
|
||||
// VC_BROKEN_STD::size_t dummy = 0);
|
||||
// and removed the ugly #pragma warning(disable:4291)"
|
||||
// Thanks to M.Yamada for the hint
|
||||
|
||||
#ifndef SMALLOBJ_INC_
|
||||
#define SMALLOBJ_INC_
|
||||
|
||||
#include "Threads.h"
|
||||
#include "Singleton.h"
|
||||
#include "MSVC6Helpers.h" // for apply-template
|
||||
#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(VC_BROKEN_STD::size_t blockSize, unsigned char blocks);
|
||||
void* Allocate(VC_BROKEN_STD::size_t blockSize);
|
||||
void Deallocate(void* p, VC_BROKEN_STD::size_t blockSize);
|
||||
void Reset(VC_BROKEN_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
|
||||
VC_BROKEN_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(VC_BROKEN_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
|
||||
VC_BROKEN_STD::size_t BlockSize() const
|
||||
{ return blockSize_; }
|
||||
// Comparison operator for sorting
|
||||
bool operator<(VC_BROKEN_STD::size_t rhs) const
|
||||
{ return BlockSize() < rhs; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SmallObjAllocator
|
||||
// Offers services for allocating small-sized objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SmallObjAllocator
|
||||
{
|
||||
public:
|
||||
SmallObjAllocator(
|
||||
VC_BROKEN_STD::size_t chunkSize,
|
||||
VC_BROKEN_STD::size_t maxObjectSize);
|
||||
|
||||
void* Allocate(VC_BROKEN_STD::size_t numBytes);
|
||||
void Deallocate(void* p, VC_BROKEN_STD::size_t size);
|
||||
|
||||
private:
|
||||
SmallObjAllocator(const SmallObjAllocator&);
|
||||
SmallObjAllocator& operator=(const SmallObjAllocator&);
|
||||
|
||||
typedef std::vector<FixedAllocator> Pool;
|
||||
Pool pool_;
|
||||
FixedAllocator* pLastAlloc_;
|
||||
FixedAllocator* pLastDealloc_;
|
||||
VC_BROKEN_STD::size_t chunkSize_;
|
||||
VC_BROKEN_STD::size_t maxObjectSize_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SmallObject
|
||||
// Base class for polymorphic small objects, offers fast
|
||||
// allocations/deallocations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class ThreadingModel = DEFAULT_THREADING,
|
||||
VC_BROKEN_STD::size_t chunkSize = DEFAULT_CHUNK_SIZE,
|
||||
VC_BROKEN_STD::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE
|
||||
>
|
||||
class SmallObject : public
|
||||
Apply1<ThreadingModel, SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >
|
||||
{
|
||||
typedef typename Apply1<ThreadingModel, SmallObject<ThreadingModel,
|
||||
chunkSize, maxSmallObjectSize> > MyThreadingModel;
|
||||
|
||||
struct MySmallObjAllocator : public SmallObjAllocator
|
||||
{
|
||||
MySmallObjAllocator()
|
||||
: SmallObjAllocator(chunkSize, maxSmallObjectSize)
|
||||
{}
|
||||
};
|
||||
// The typedef below would make things much simpler,
|
||||
// but MWCW won't like it
|
||||
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
|
||||
// DefaultLifetime, ThreadingModel*/> MyAllocator;
|
||||
|
||||
public:
|
||||
static void* operator new(VC_BROKEN_STD::size_t size, VC_BROKEN_STD::size_t dummy = 0)
|
||||
{
|
||||
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
|
||||
return SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||
PhoenixSingleton>::Instance().Allocate(size);
|
||||
#else
|
||||
return ::operator new(size);
|
||||
#endif
|
||||
}
|
||||
static void operator delete(void* p, VC_BROKEN_STD::size_t size)
|
||||
{
|
||||
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0)
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
|
||||
SingletonHolder<MySmallObjAllocator, CreateStatic,
|
||||
PhoenixSingleton>::Instance().Deallocate(p, size);
|
||||
#else
|
||||
::operator delete(p, size);
|
||||
#endif
|
||||
}
|
||||
virtual ~SmallObject() {}
|
||||
};
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Oct 11, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SMALLOBJ_INC_
|
1498
include/noncc/MSVC/1200/SmartPtr.h
Executable file
1498
include/noncc/MSVC/1200/SmartPtr.h
Executable file
File diff suppressed because it is too large
Load diff
228
include/noncc/MSVC/1200/Threads.h
Executable file
228
include/noncc/MSVC/1200/Threads.h
Executable file
|
@ -0,0 +1,228 @@
|
|||
#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: Mar 26, 2003
|
||||
// note: In this VC 6 port all template policies become non-templates with
|
||||
// either member-template functions or a nested template struct named In
|
||||
|
||||
// Changed wrong ctor/dtor names in ObjectLevelLockable.
|
||||
// Thanks to Adi Shavit for pointing that out
|
||||
|
||||
#ifndef DEFAULT_THREADING
|
||||
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
||||
#endif
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingleThreaded
|
||||
// Implementation of the ThreadingModel policy used by various classes
|
||||
// Implements a single-threaded model; no synchronization
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class SingleThreaded
|
||||
{
|
||||
public:
|
||||
template <class Host>
|
||||
struct In
|
||||
{
|
||||
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; }
|
||||
|
||||
// The following function uses the undefined variable val.
|
||||
// Moreover I couldn't find the function in the orginial loki-lib.
|
||||
// I therefore commented the function out
|
||||
/*
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct ObjectLevelLockable
|
||||
{
|
||||
template <class Host>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION mtx_;
|
||||
|
||||
public:
|
||||
In()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
~In()
|
||||
{
|
||||
::DeleteCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
class Lock;
|
||||
friend class Lock;
|
||||
|
||||
class Lock
|
||||
{
|
||||
ObjectLevelLockable::In<Host>& host_;
|
||||
|
||||
Lock(const Lock&);
|
||||
Lock& operator=(const Lock&);
|
||||
//Lock(); // buggy design
|
||||
public:
|
||||
|
||||
explicit Lock(ObjectLevelLockable::In<Host>& host) : host_(host)
|
||||
{
|
||||
::EnterCriticalSection(&host_.mtx_);
|
||||
}
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&host_.mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
typedef volatile Host VolatileType;
|
||||
|
||||
typedef LONG IntType;
|
||||
|
||||
static IntType AtomicIncrement(volatile IntType& lval)
|
||||
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static IntType 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); }
|
||||
};
|
||||
};
|
||||
|
||||
struct ClassLevelLockable
|
||||
{
|
||||
template <class Host>
|
||||
struct In
|
||||
{
|
||||
public:
|
||||
struct Initializer;
|
||||
friend struct Initializer;
|
||||
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 Loki::ClassLevelLockable::template In<Host>::Initializer
|
||||
Loki::ClassLevelLockable::template In<Host>::initializer_;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Oct 06, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// Feb 20, 2003: corrected constructor parameter in ObjectLevelLockable::Lock
|
||||
// Mar 26, 2003: added Loki-Namespace-Qualification to definition of
|
||||
// ClassLevelLockable's static member.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
22
include/noncc/MSVC/1200/Tuple.h
Executable file
22
include/noncc/MSVC/1200/Tuple.h
Executable file
|
@ -0,0 +1,22 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This file is intentionally left empty
|
||||
// Due to compiler limitations, its contents has been moved to
|
||||
// HierarchyGenerators.h
|
||||
////////////////////////////////////////////////////////////////////////////////
|
269
include/noncc/MSVC/1200/TypeManip.h
Executable file
269
include/noncc/MSVC/1200/TypeManip.h
Executable file
|
@ -0,0 +1,269 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Oct 17, 2002
|
||||
|
||||
#include "static_check.h"
|
||||
|
||||
#ifndef TYPEMANIP_INC_
|
||||
#define TYPEMANIP_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
namespace Private
|
||||
{
|
||||
typedef char YES;
|
||||
struct NO {char dummy[3];};
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Int2Type
|
||||
// Converts each integral constant into a unique type
|
||||
// Invocation: Int2Type<v> where v is a compile-time constant integral
|
||||
// Defines 'value', an enum that evaluates to v
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <int v>
|
||||
struct Int2Type
|
||||
{
|
||||
Int2Type() {}
|
||||
enum { value = v };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Type2Type
|
||||
// Converts each type into a unique, insipid type
|
||||
// Invocation Type2Type<T> where T is a type
|
||||
// Defines the type OriginalType which maps back to T
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct Type2Type
|
||||
{
|
||||
typedef T OriginalType;
|
||||
Type2Type() {};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Select
|
||||
// Selects one of two types based upon a boolean constant
|
||||
// Invocation: Select<flag, T, U>::Result
|
||||
// where:
|
||||
// flag is a compile-time boolean constant
|
||||
// T and U are types
|
||||
// Result evaluates to T if flag is true, and to U otherwise.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// VC6 compatible version
|
||||
namespace Private
|
||||
{
|
||||
template <bool>
|
||||
struct SelectImpl
|
||||
{
|
||||
template <class T, class U>
|
||||
struct In
|
||||
{
|
||||
typedef T Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SelectImpl<false>
|
||||
{
|
||||
template <class T, class U>
|
||||
struct In
|
||||
{
|
||||
typedef U Result;
|
||||
};
|
||||
};
|
||||
|
||||
} // end of namespace private
|
||||
template <bool flag, typename T, typename U>
|
||||
struct Select
|
||||
{
|
||||
typedef typename Private::SelectImpl<flag>::template In<T, U>::Result Result;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsEqualType
|
||||
// Returns true if the two given types are equal
|
||||
// Invocation: IsEqualType<T, U>::value
|
||||
// where:
|
||||
// T and U are types
|
||||
// Result evaluates to true if U == T (types equal)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This template is not in the original Loki-Library
|
||||
template <class T, class U>
|
||||
struct IsEqualType
|
||||
{
|
||||
private:
|
||||
static Private::YES check(Type2Type<T>);
|
||||
static Private::NO check(...);
|
||||
public:
|
||||
enum {value = sizeof(check(Type2Type<U>())) == sizeof(Private::YES)};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
typedef char Small;
|
||||
class Big { char dummy[2]; };
|
||||
|
||||
// IsVoid from Rani Sharoni's VC 7 port
|
||||
template<typename T>
|
||||
struct IsVoid
|
||||
{
|
||||
enum { value =
|
||||
IsEqualType<T, void>::value ||
|
||||
IsEqualType<T, const void>::value ||
|
||||
IsEqualType<T, volatile void>::value ||
|
||||
IsEqualType<T, const volatile void>::value
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// is one type convertable to another?
|
||||
//
|
||||
// is_convertible from Rani Sharoni's VC 7 port.
|
||||
template <class T, class U>
|
||||
class is_convertible
|
||||
{
|
||||
struct VoidReplace {};
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
Private::IsVoid<T>::value,
|
||||
VoidReplace, T
|
||||
>
|
||||
::Result T1;
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
Private::IsVoid<U>::value,
|
||||
VoidReplace, U
|
||||
>
|
||||
::Result U1;
|
||||
|
||||
static Private::Big Test(...);
|
||||
static Private::Small Test(U1);
|
||||
static T1 MakeT();
|
||||
|
||||
public:
|
||||
enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Conversion
|
||||
// Figures out the conversion relationships between two types
|
||||
// Invocations (T and U are types):
|
||||
// a) Conversion<T, U>::exists
|
||||
// returns (at compile time) true if there is an implicit conversion from T
|
||||
// to U (example: Derived to Base)
|
||||
// b) Conversion<T, U>::exists2Way
|
||||
// returns (at compile time) true if there are both conversions from T
|
||||
// to U and from U to T (example: int to char and back)
|
||||
// c) Conversion<T, U>::sameType
|
||||
// returns (at compile time) true if T and U represent the same type
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Conversion-Template from Rani Sharoni's VC 7 port.
|
||||
template <class T, class U>
|
||||
struct Conversion
|
||||
{
|
||||
enum { exists = (is_convertible<T,U>::exists) };
|
||||
enum { exists2Way = (exists && is_convertible<U, T>::exists) };
|
||||
enum { sameType = (IsEqualType<T, U>::value) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SuperSubclass
|
||||
// Invocation: SuperSubclass<B, D>::value where B and D are types.
|
||||
// Returns true if B is a public base of D, or if B and D are aliases of the
|
||||
// same type.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class U>
|
||||
struct SuperSubclass
|
||||
{
|
||||
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SuperSubclassStrict
|
||||
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
|
||||
// Returns true if B is a public base of D.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T,class U>
|
||||
struct SuperSubclassStrict
|
||||
{
|
||||
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro SUPERSUBCLASS
|
||||
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
|
||||
// Returns true if B is a public base of D, or if B and D are aliases of the
|
||||
// same type.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS(T, U) \
|
||||
(::Loki::Conversion<const volatile U*, const volatile T*>::exists && \
|
||||
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro SUPERSUBCLASS
|
||||
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
|
||||
// Returns true if B is a public base of D.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS_STRICT(T, U) \
|
||||
(SUPERSUBCLASS(T, U) && \
|
||||
!::Loki::Conversion<const volatile T *, const volatile U *>::sameType)
|
||||
|
||||
|
||||
|
||||
template <unsigned i>
|
||||
struct TypeTag
|
||||
{
|
||||
struct Inner {char c[i];};
|
||||
typedef Inner X;
|
||||
STATIC_SIZE_ASSERT(X, i);
|
||||
};
|
||||
|
||||
} // 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)
|
||||
// Sept 29, 2002: ported by Benjamin Kaufmann to MSVC 6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPEMANIP_INC_
|
||||
|
471
include/noncc/MSVC/1200/TypeTraits.h
Executable file
471
include/noncc/MSVC/1200/TypeTraits.h
Executable file
|
@ -0,0 +1,471 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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: Feb 16, 2003
|
||||
// Added isFunctionPointer to TypeTraits.
|
||||
//
|
||||
// This VC 6 port of TypeTraits is based on Rani Sharoni's Loki VC 7 port.
|
||||
// Reference, pointer, array, const and volatile detection is based on
|
||||
// boost's type traits.
|
||||
// see http://www.boost.org/libs/type_traits/
|
||||
//
|
||||
// The code for Enum- and pointer-to-member-function detection is based on
|
||||
// ideas from M. Yamada - many thanks :)
|
||||
//
|
||||
// AdjReference has moved to namespace-scope. Explicit specialization is
|
||||
// only allowed there.
|
||||
//
|
||||
// known bugs:
|
||||
// assert(TypeTraits<const void>::isConst == 1) fails.
|
||||
// assert(TypeTraits<volatile void>::isVolatile == 1) fails.
|
||||
// assert(TypeTraits<const volatile void>::isConst == 1) fails.
|
||||
// assert(TypeTraits<const volatile void>::isVolatile == 1) fails.
|
||||
// This is because the VC 6 does not differentiate
|
||||
// between void, const void, volatile void and const volatile void.
|
||||
|
||||
#ifndef TYPETRAITS_INC_
|
||||
#define TYPETRAITS_INC_
|
||||
|
||||
//
|
||||
// Ignore forcing value to bool 'true' or 'false' (performance warning)
|
||||
//
|
||||
#ifdef _MSC_VER
|
||||
#include <cctype> // for wchar_t
|
||||
#pragma warning (disable: 4800)
|
||||
#endif
|
||||
|
||||
#include "Typelist.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomUnsignedInt
|
||||
// Offers a means to integrate nonstandard built-in unsigned integral types
|
||||
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
|
||||
// class template defined below.
|
||||
// Invocation: IsCustomUnsignedInt<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
|
||||
// integral type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomUnsignedInt
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomSignedInt
|
||||
// Offers a means to integrate nonstandard built-in unsigned integral types
|
||||
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
|
||||
// class template defined below.
|
||||
// Invocation: IsCustomSignedInt<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in signed
|
||||
// integral type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomSignedInt
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomFloat
|
||||
// Offers a means to integrate nonstandard floating point types with the
|
||||
// TypeTraits class template defined below.
|
||||
// Invocation: IsCustomFloat<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in
|
||||
// floating point type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomFloat
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types for class template TypeTraits defined below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
typedef TYPELIST_4(unsigned char, unsigned short int,
|
||||
unsigned int, unsigned long int) StdUnsignedInts;
|
||||
typedef TYPELIST_4(signed char, short int,
|
||||
int, long int) StdSignedInts;
|
||||
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
|
||||
typedef TYPELIST_3(float, double, long double) StdFloats;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template TypeTraits
|
||||
// Figures out various properties of any given type
|
||||
// Invocations (T is a type):
|
||||
// a) TypeTraits<T>::isPointer
|
||||
// returns (at compile time) true if T is a pointer type
|
||||
// b) TypeTraits<T>::PointeeType
|
||||
// returns the type to which T points is T is a pointer type, NullType otherwise
|
||||
// a) TypeTraits<T>::isReference
|
||||
// returns (at compile time) true if T is a reference type
|
||||
// b) TypeTraits<T>::ReferredType
|
||||
// returns the type to which T refers is T is a reference type, NullType
|
||||
// otherwise
|
||||
// c) TypeTraits<T>::isMemberPointer
|
||||
// returns (at compile time) true if T is a pointer to member type
|
||||
// d) TypeTraits<T>::isStdUnsignedInt
|
||||
// returns (at compile time) true if T is a standard unsigned integral type
|
||||
// e) TypeTraits<T>::isStdSignedInt
|
||||
// returns (at compile time) true if T is a standard signed integral type
|
||||
// f) TypeTraits<T>::isStdIntegral
|
||||
// returns (at compile time) true if T is a standard integral type
|
||||
// g) TypeTraits<T>::isStdFloat
|
||||
// returns (at compile time) true if T is a standard floating-point type
|
||||
// h) TypeTraits<T>::isStdArith
|
||||
// returns (at compile time) true if T is a standard arithmetic type
|
||||
// i) TypeTraits<T>::isStdFundamental
|
||||
// returns (at compile time) true if T is a standard fundamental type
|
||||
// j) TypeTraits<T>::isUnsignedInt
|
||||
// returns (at compile time) true if T is a unsigned integral type
|
||||
// k) TypeTraits<T>::isSignedInt
|
||||
// returns (at compile time) true if T is a signed integral type
|
||||
// l) TypeTraits<T>::isIntegral
|
||||
// returns (at compile time) true if T is a integral type
|
||||
// m) TypeTraits<T>::isFloat
|
||||
// returns (at compile time) true if T is a floating-point type
|
||||
// n) TypeTraits<T>::isArith
|
||||
// returns (at compile time) true if T is a arithmetic type
|
||||
// o) TypeTraits<T>::isFundamental
|
||||
// returns (at compile time) true if T is a fundamental type
|
||||
// p) TypeTraits<T>::ParameterType
|
||||
// returns the optimal type to be used as a parameter for functions that take Ts
|
||||
// q) TypeTraits<T>::isConst
|
||||
// returns (at compile time) true if T is a const-qualified type
|
||||
// r) TypeTraits<T>::NonConstType
|
||||
// removes the 'const' qualifier from T, if any
|
||||
// s) TypeTraits<T>::isVolatile
|
||||
// returns (at compile time) true if T is a volatile-qualified type
|
||||
// t) TypeTraits<T>::NonVolatileType
|
||||
// removes the 'volatile' qualifier from T, if any
|
||||
// u) TypeTraits<T>::UnqualifiedType
|
||||
// removes both the 'const' and 'volatile' qualifiers from T, if any
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
// const-detection based on boost's
|
||||
// Type-Traits. See: boost\type_traits\is_const.hpp
|
||||
YES IsConstTester(const volatile void*);
|
||||
NO IsConstTester(volatile void *);
|
||||
|
||||
template <bool is_ref, bool array>
|
||||
struct IsConstImpl
|
||||
{
|
||||
template <class T> struct In {enum {value=0};};
|
||||
};
|
||||
template <>
|
||||
struct IsConstImpl<false,false>
|
||||
{
|
||||
template <typename T> struct In
|
||||
{
|
||||
static T* t;
|
||||
enum {value = sizeof(YES) == sizeof(IsConstTester(t))};
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct IsConstImpl<false,true>
|
||||
{
|
||||
template <typename T> struct In
|
||||
{
|
||||
static T t;
|
||||
enum { value = sizeof(YES) == sizeof(IsConstTester(&t)) };
|
||||
};
|
||||
};
|
||||
|
||||
// this volatile-detection approach is based on boost's
|
||||
// Type-Traits. See: boost\type_traits\is_volatile.hpp
|
||||
YES IsVolatileTester(void const volatile*);
|
||||
NO IsVolatileTester(void const*);
|
||||
|
||||
template <bool is_ref, bool array>
|
||||
struct IsVolatileImpl
|
||||
{
|
||||
template <typename T> struct In
|
||||
{
|
||||
enum {value = 0};
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsVolatileImpl<false,false>
|
||||
{
|
||||
template <typename T> struct In
|
||||
{
|
||||
static T* t;
|
||||
enum {value = sizeof(YES) == sizeof(IsVolatileTester(t))};
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsVolatileImpl<false,true>
|
||||
{
|
||||
template <typename T> struct In
|
||||
{
|
||||
static T t;
|
||||
enum {value = sizeof(YES) == sizeof(IsVolatileTester(&t))};
|
||||
};
|
||||
};
|
||||
|
||||
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; };
|
||||
};
|
||||
struct PointerHelper
|
||||
{
|
||||
PointerHelper(const volatile void*);
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
NO EnumDetection(T);
|
||||
|
||||
template <class T>
|
||||
YES EnumDetection(...);
|
||||
|
||||
YES IsPointer(PointerHelper);
|
||||
NO IsPointer(...);
|
||||
|
||||
// With the VC 6. Rani Sharoni's approach to detect references unfortunately
|
||||
// results in an error C1001: INTERNAL COMPILER-ERROR
|
||||
//
|
||||
// this reference-detection approach is based on boost's
|
||||
// Type-Traits. See: boost::composite_traits.h
|
||||
//
|
||||
// is_reference_helper1 is a function taking a Type2Type<T> returning
|
||||
// a pointer to a function taking a Type2Type<T> returning a T&.
|
||||
// This function can only be used if T is not a reference-Type.
|
||||
// If T is a reference Type the return type would be
|
||||
// a function taking a Type2Type<T> returning a reference to a T-reference.
|
||||
// That is illegal, therefore is_reference_helper1(...) is used for
|
||||
// references.
|
||||
// In order to detect a reference, use the return-type of is_reference_helper1
|
||||
// with is_reference_helper2.
|
||||
//
|
||||
template <class U>
|
||||
U&(* IsReferenceHelper1(::Loki::Type2Type<U>) )(::Loki::Type2Type<U>);
|
||||
NO IsReferenceHelper1(...);
|
||||
|
||||
template <class U>
|
||||
NO IsReferenceHelper2(U&(*)(::Loki::Type2Type<U>));
|
||||
YES IsReferenceHelper2(...);
|
||||
|
||||
template <class U, class Z>
|
||||
YES IsPointer2Member(Z U::*);
|
||||
NO IsPointer2Member(...);
|
||||
|
||||
// this array-detection approach is based on boost's
|
||||
// Type-Traits. See: boost::array_traits.hpp
|
||||
|
||||
// This function can only be used for non-array-types, because
|
||||
// functions can't return arrays.
|
||||
template<class U>
|
||||
U(* IsArrayTester1(::Loki::Type2Type<U>) )(::Loki::Type2Type<U>);
|
||||
char IsArrayTester1(...);
|
||||
|
||||
template<class U>
|
||||
NO IsArrayTester2(U(*)(::Loki::Type2Type<U>));
|
||||
YES IsArrayTester2(...);
|
||||
|
||||
// Helper functions for function-pointer detection.
|
||||
// The code uses the fact, that arrays of functions are not allowed.
|
||||
// Of course TypeTraits first makes sure that U is neither void
|
||||
// nor a reference.type.
|
||||
// The idea for this code is from D Vandevoorde's & N. Josuttis'
|
||||
// book "C++ Templates".
|
||||
template<class U>
|
||||
NO IsFunctionPtrTester1(U*, U(*)[1] = 0);
|
||||
YES IsFunctionPtrTester1(...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class TypeTraits
|
||||
{
|
||||
public:
|
||||
enum { isVoid = Private::IsVoid<T>::value};
|
||||
enum { isStdUnsignedInt =
|
||||
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0 };
|
||||
enum { isStdSignedInt =
|
||||
TL::IndexOf<Private::StdSignedInts, T>::value >= 0 };
|
||||
enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
|
||||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0 };
|
||||
enum { isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0 };
|
||||
enum { isStdArith = isStdIntegral || isStdFloat };
|
||||
enum { isStdFundamental = isStdArith || isStdFloat || isVoid };
|
||||
|
||||
enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
|
||||
enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
|
||||
enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
|
||||
enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
|
||||
enum { isArith = isIntegral || isFloat };
|
||||
enum { isFundamental = isStdFundamental || isArith || isFloat };
|
||||
|
||||
enum { isArray = sizeof(Private::YES)
|
||||
== sizeof(Private::IsArrayTester2(
|
||||
Private::IsArrayTester1(::Loki::Type2Type<T>()))
|
||||
)
|
||||
};
|
||||
|
||||
enum { isReference = sizeof(Private::YES)
|
||||
== sizeof(Private::IsReferenceHelper2(
|
||||
Private::IsReferenceHelper1(::Loki::Type2Type<T>()))
|
||||
) && !isVoid
|
||||
};
|
||||
enum { isConst = Private::IsConstImpl
|
||||
<isReference, isArray>::template In<T>::value
|
||||
};
|
||||
|
||||
enum { isVolatile = Private::IsVolatileImpl
|
||||
<isReference, isArray>::template In<T>::value
|
||||
};
|
||||
private:
|
||||
typedef typename Private::AdjReference<isReference || isVoid>::
|
||||
template In<T>::Result AdjType;
|
||||
|
||||
struct is_scalar
|
||||
{
|
||||
private:
|
||||
struct BoolConvert { BoolConvert(bool); };
|
||||
|
||||
static Private::YES check(BoolConvert);
|
||||
static Private::NO check(...);
|
||||
|
||||
struct NotScalar {};
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isVoid || isReference || isArray,
|
||||
NotScalar, T
|
||||
>
|
||||
::Result RetType;
|
||||
|
||||
// changed to RetType& to allow testing of abstract classes
|
||||
static RetType& get();
|
||||
|
||||
public:
|
||||
enum { value = sizeof(check(get())) == sizeof(Private::YES) };
|
||||
|
||||
|
||||
}; // is_scalar
|
||||
|
||||
public:
|
||||
enum { isScalar = is_scalar::value};
|
||||
typedef typename Select
|
||||
<
|
||||
isScalar || isArray, T, AdjType
|
||||
>
|
||||
::Result ParameterType;
|
||||
private:
|
||||
|
||||
typedef typename Loki::Select
|
||||
<
|
||||
isScalar,
|
||||
T,
|
||||
int
|
||||
>::Result TestType;
|
||||
static TestType MakeT();
|
||||
|
||||
enum { isMemberPointerTemp = sizeof(Private::YES)
|
||||
== sizeof(Private::IsPointer2Member(MakeT()))
|
||||
};
|
||||
public:
|
||||
enum {isPointer = sizeof(Private::YES)
|
||||
== sizeof(Private::IsPointer(MakeT()))};
|
||||
private:
|
||||
typedef typename Loki::Select
|
||||
<
|
||||
isVoid || isReference || !isPointer,
|
||||
int*,
|
||||
T
|
||||
>::Result MayBeFuncPtr;
|
||||
public:
|
||||
// enum types are the only scalar types that can't be initialized
|
||||
// with 0.
|
||||
// Because we replace all non scalars with int,
|
||||
// template <class T>
|
||||
// YES EnumDetection(...);
|
||||
// will only be selected for enums.
|
||||
enum { isEnum = sizeof(Private::YES)
|
||||
== sizeof (Private::EnumDetection<TestType>(0))
|
||||
};
|
||||
|
||||
enum { isMemberFunctionPointer = isScalar && !isArith && !isPointer &&
|
||||
!isMemberPointerTemp && !isEnum
|
||||
};
|
||||
enum { isMemberPointer = isMemberPointerTemp || isMemberFunctionPointer};
|
||||
|
||||
enum { isFunctionPointer = sizeof(Private::YES)
|
||||
== sizeof(
|
||||
Private::IsFunctionPtrTester1(MayBeFuncPtr(0))
|
||||
) && !isMemberPointer
|
||||
};
|
||||
//
|
||||
// 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 &&
|
||||
!isEnum
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default: 4800)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
// Oct 05, 2002: ported by Benjamin Kaufmann to MSVC 6
|
||||
// Jan 31, 2003: fixed bugs in scalar and array detection.
|
||||
// Added isMemberFuncPointer and isEnum. B.K.
|
||||
//
|
||||
// Feb 16, 2003: fixed bug in reference-Detection. Renamed isMemberFuncPointer
|
||||
// to isMemberFunctionPointer. Added isFunctionPointer, replaced
|
||||
// all occurrences of Private::Wrap with Loki::Type2Type and
|
||||
// cleaned up the TypeTraits-class. B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPETRAITS_INC_
|
1148
include/noncc/MSVC/1200/Typelist.h
Executable file
1148
include/noncc/MSVC/1200/Typelist.h
Executable file
File diff suppressed because it is too large
Load diff
520
include/noncc/MSVC/1200/Visitor.h
Executable file
520
include/noncc/MSVC/1200/Visitor.h
Executable file
|
@ -0,0 +1,520 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Mar 06, 2003
|
||||
//
|
||||
// Like the original library, this port now uses void as
|
||||
// default value for return types.
|
||||
//
|
||||
// This new of visitor.h handles void returns transparently. See
|
||||
// readme.txt for an explanation of the used technique.
|
||||
// However there are still two sets of macros. One for return type = void
|
||||
// (DEFINE_VISITABLE_VOID, DEFINE_CYCLIC_VISITABLE_VOID) and one for return
|
||||
// type != void (DEFINE_VISITABLE, DEFINE_CYCLIC_VISITABLE)
|
||||
//
|
||||
// If you prefer the old version of visitor.h which uses a different set of
|
||||
// visitor classes for the return type void, define the macro
|
||||
// USE_VISITOR_OLD_VERSION.
|
||||
//
|
||||
#ifdef USE_VISITOR_OLD_VERSION
|
||||
#include "VisitorOld.h"
|
||||
#else
|
||||
#ifndef VISITOR_INC_
|
||||
#define VISITOR_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
#include "MSVC6Helpers.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template BaseVisitor
|
||||
// The base class of any Acyclic Visitor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BaseVisitor
|
||||
{
|
||||
public:
|
||||
virtual ~BaseVisitor() {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Visitor
|
||||
// The building block of Acyclic Visitor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T, typename R = Loki::Private::VoidWrap::type >
|
||||
class Visitor;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Visitor (specialization)
|
||||
// This specialization is not present in the book. It makes it easier to define
|
||||
// Visitors for multiple types in a shot by using a typelist. Example:
|
||||
//
|
||||
// class SomeVisitor :
|
||||
// public BaseVisitor // required
|
||||
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
|
||||
// public Visitor<Paragraph>
|
||||
// {
|
||||
// public:
|
||||
// void Visit(RasterBitmap&); // visit a RasterBitmap
|
||||
// void Visit(Paragraph &); // visit a Paragraph
|
||||
// };
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
// helper for Visitor's the left base class
|
||||
template <unsigned int ListId>
|
||||
struct VisitorImplLeft
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
// helper for Visitor's the right base class
|
||||
template <unsigned int ListId>
|
||||
struct VisitorImplRight
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
// simulates specialization
|
||||
// class Visitor<Head, R>
|
||||
template <>
|
||||
struct VisitorImplLeft<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class T, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
typedef R ReturnType;
|
||||
virtual ReturnType Visit(T&) = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// simulates the left base class for the specialization
|
||||
// class Visitor<Typelist<Head, Tail>, R>
|
||||
template <>
|
||||
struct VisitorImplLeft<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef Visitor<typename TList::Head, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
// simulates the right base class for the specialization
|
||||
// class Visitor<Typelist<Head, Tail>, R>
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef Visitor<typename TList::Tail, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::AtomList_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
// MSVC 6.0 will complain if we try to let Visitor inherit
|
||||
// directly from VisitorImplLeft/VisitorImplRight
|
||||
template <class T, class R>
|
||||
struct VisitorImplLeftWrap
|
||||
{
|
||||
struct Dummy{};
|
||||
typedef typename VisitorImplLeft
|
||||
<
|
||||
TL::Private::IsTypelist<T>::type_id == TL::Private::AtomList_ID ?
|
||||
TL::Private::Typelist_ID :
|
||||
TL::Private::IsTypelist<T>::type_id
|
||||
>::template In<T, R>::Result TempType;
|
||||
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
struct VisitorImplRightWrap
|
||||
{
|
||||
struct Dummy{};
|
||||
typedef typename VisitorImplRight
|
||||
<
|
||||
TL::Private::IsTypelist<T>::type_id
|
||||
>::template In<T, R>::Result TempType;
|
||||
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
template <class T, typename R>
|
||||
class Visitor : public Private::VisitorImplLeftWrap<T, R>::Result,
|
||||
public Private::VisitorImplRightWrap<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 = Loki::Private::VoidWrap::type >
|
||||
class BaseVisitorImpl;
|
||||
namespace Private
|
||||
{
|
||||
template <unsigned int ListTag>
|
||||
struct BaseVisitorImplHelper
|
||||
{
|
||||
template <typename T, typename R>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BaseVisitorImplHelper<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <typename TList, typename R>
|
||||
struct In
|
||||
{
|
||||
typedef BaseVisitorImpl<TList, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BaseVisitorImplHelper<TL::Private::NullType_ID>
|
||||
{
|
||||
template <typename TList, typename R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
struct BaseVisitorImplWrap
|
||||
{
|
||||
struct Dummy {};
|
||||
typedef typename BaseVisitorImplHelper
|
||||
<
|
||||
TL::Private::IsTypelist<typename T::Tail>::
|
||||
type_id == TL::Private::AtomList_ID ?
|
||||
TL::Private::Typelist_ID :
|
||||
TL::Private::IsTypelist<typename T::Tail>::type_id
|
||||
>::template In<typename T::Tail, R>::Result TempType;
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
template <class TList, class R>
|
||||
struct BaseVisitorImplBase : public Visitor<typename TList::Head, R>,
|
||||
public Private::BaseVisitorImplWrap<TList, R>::Result
|
||||
{
|
||||
ASSERT_TYPELIST(TList);
|
||||
virtual R Visit(typename TList::Head&)
|
||||
{ return R(); }
|
||||
protected:
|
||||
~BaseVisitorImplBase() {}
|
||||
};
|
||||
|
||||
template <class TList, class R>
|
||||
struct BaseVisitorImplVoidBase : public Visitor<typename TList::Head, R>,
|
||||
public Private::BaseVisitorImplWrap<TList, R>::Result
|
||||
{
|
||||
|
||||
ASSERT_TYPELIST(TList);
|
||||
virtual R Visit(typename TList::Head&)
|
||||
{ }
|
||||
protected:
|
||||
~BaseVisitorImplVoidBase() {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template <class TList, typename R>
|
||||
class BaseVisitorImpl : public Select
|
||||
<
|
||||
Private::IsVoid<R>::value,
|
||||
Private::BaseVisitorImplVoidBase<TList,R>,
|
||||
Private::BaseVisitorImplBase<TList, R>
|
||||
>::Result
|
||||
{
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
public:
|
||||
// using BaseVisitorImpl<Tail, R>::Visit;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultCatchAll
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename R, typename Visited>
|
||||
struct DefaultCatchAll
|
||||
{
|
||||
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
||||
{ return R(); }
|
||||
};
|
||||
template <typename R, typename Visited>
|
||||
struct DefaultCatchAllVoid
|
||||
{
|
||||
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
||||
{ }
|
||||
};
|
||||
|
||||
// template template parameter workaround.
|
||||
// use Wrapper-Classes like this to instantiate BaseVisitable
|
||||
struct DefaultCatchAllWrapper
|
||||
{
|
||||
template <class R, class Visited>
|
||||
struct In
|
||||
{
|
||||
typedef typename Select<Private::IsVoid<R>::value,
|
||||
DefaultCatchAllVoid<R, Visited>,
|
||||
DefaultCatchAll<R, Visited>
|
||||
>::Result type;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 T, class Base>
|
||||
struct NonStrictVisitorUnitVoid : public Base
|
||||
{
|
||||
typedef typename Base::ReturnType ReturnType;
|
||||
ReturnType Visit(T&)
|
||||
{}
|
||||
};
|
||||
|
||||
struct NonStrictVisitorUnitWrapper
|
||||
{
|
||||
template <class T, class B>
|
||||
struct In
|
||||
{
|
||||
typedef typename B::ReturnType R;
|
||||
typedef typename Select<Private::IsVoid<R>::value,
|
||||
NonStrictVisitorUnitVoid<T, B>,
|
||||
NonStrictVisitorUnit<T, B>
|
||||
>::Result type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class TList, typename R = Loki::Private::VoidWrap::type>
|
||||
class NonStrictVisitor
|
||||
: public GenLinearHierarchy<
|
||||
TList,
|
||||
NonStrictVisitorUnitWrapper,
|
||||
Visitor<TList, R> >
|
||||
{
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template BaseVisitable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
template <class R, class CatchAll>
|
||||
class BaseVisitableBase
|
||||
{
|
||||
typedef R ReturnType;
|
||||
protected:
|
||||
template <class T>
|
||||
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
||||
{
|
||||
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
|
||||
// Apply the Acyclic Visitor
|
||||
if (Visitor<T, R>* p = dynamic_cast<Visitor<T, R>*>(&guest))
|
||||
{
|
||||
return p->Visit(visited);
|
||||
}
|
||||
return CatchA::OnUnknownVisitor(visited, guest);
|
||||
}
|
||||
~BaseVisitableBase() {}
|
||||
|
||||
};
|
||||
template <class R, class CatchAll>
|
||||
class BaseVisitableVoidBase
|
||||
{
|
||||
typedef R ReturnType;
|
||||
protected:
|
||||
template <class T>
|
||||
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
||||
{
|
||||
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
|
||||
// Apply the Acyclic Visitor
|
||||
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
|
||||
{
|
||||
p->Visit(visited);
|
||||
return;
|
||||
}
|
||||
CatchA::OnUnknownVisitor(visited, guest);
|
||||
}
|
||||
~BaseVisitableVoidBase() {}
|
||||
};
|
||||
}
|
||||
template
|
||||
<
|
||||
typename R = Loki::Private::VoidWrap::type,
|
||||
class CatchAll = DefaultCatchAllWrapper
|
||||
>
|
||||
class BaseVisitable : public Select<Private::IsVoid<R>::value,
|
||||
Private::BaseVisitableVoidBase<R, CatchAll>,
|
||||
Private::BaseVisitableBase<R, CatchAll>
|
||||
>::Result
|
||||
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
virtual ~BaseVisitable() {}
|
||||
virtual ReturnType Accept(BaseVisitor&) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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(Loki::BaseVisitor& guest) \
|
||||
{ return AcceptImpl(*this, guest); }
|
||||
|
||||
#define DEFINE_VISITABLE_VOID() \
|
||||
virtual ReturnType Accept(Loki::BaseVisitor& guest) \
|
||||
{ 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>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
template <typename R, class TList>
|
||||
class CyclicVisitorBase : public Visitor<TList, R>
|
||||
{
|
||||
public:
|
||||
template <class Visited>
|
||||
ReturnType GenericVisit(Visited& host)
|
||||
{
|
||||
Visitor<Visited, ReturnType>& subObj = *this;
|
||||
return subObj.Visit(host);
|
||||
}
|
||||
protected:
|
||||
~CyclicVisitorBase() {}
|
||||
};
|
||||
template <class TList>
|
||||
class CyclicVisitorVoidBase : public Visitor<TList, void>
|
||||
{
|
||||
public:
|
||||
template <class Visited>
|
||||
ReturnType GenericVisit(Visited& host)
|
||||
{
|
||||
Visitor<Visited, ReturnType>& subObj = *this;
|
||||
subObj.Visit(host);
|
||||
}
|
||||
protected:
|
||||
~CyclicVisitorVoidBase() {}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename R, class TList>
|
||||
class CyclicVisitor : public Select<Private::IsVoid<R>::value,
|
||||
Private::CyclicVisitorVoidBase<TList>,
|
||||
Private::CyclicVisitorBase<R, TList>
|
||||
>::Result
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
// using Visitor<TList, R>::Visit;
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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); }
|
||||
|
||||
#define DEFINE_CYCLIC_VISITABLE_VOID(SomeVisitor) \
|
||||
virtual void Accept(SomeVisitor& guest) \
|
||||
{ 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!!!
|
||||
// Oct 27, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// Feb 23, 2003: Removed special visitor classes for return type void.
|
||||
// Added Loki:: qualification to Accept's Paramter (in the macro) B.K.
|
||||
// Mar 06, 2003: Changed default values for return types to void.
|
||||
// Added protected destructors to private implementation classes B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // VISITOR_INC_
|
||||
#endif
|
521
include/noncc/MSVC/1200/VisitorOld.h
Executable file
521
include/noncc/MSVC/1200/VisitorOld.h
Executable file
|
@ -0,0 +1,521 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Feb 23, 2003
|
||||
//
|
||||
//
|
||||
// The original visitor implementation depends heavily on the possibility
|
||||
// to return an expression of type "cv void" from a functions with a return
|
||||
// type of cv void (6.6.3).
|
||||
// Unfortunately the MSVC 6.0 does not allow that. Because I could not think
|
||||
// of any transparent workaround I decided to create a set of complete new
|
||||
// classes for the void-case.
|
||||
// Of course this is a very unattractive solution :-(
|
||||
// If you know of a better solution, please let me know.
|
||||
//
|
||||
// The MSVC 6.0 does not allow void to be a default value for a template parameter.
|
||||
// I therefore changed all defaults to int.
|
||||
|
||||
#ifndef VISITOR_INC_
|
||||
#define VISITOR_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
#include "MSVC6Helpers.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template BaseVisitor
|
||||
// The base class of any Acyclic Visitor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BaseVisitor
|
||||
{
|
||||
public:
|
||||
virtual ~BaseVisitor() {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Visitor
|
||||
// The building block of Acyclic Visitor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T, typename R = int/* = void */ >
|
||||
class Visitor;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Visitor (specialization)
|
||||
// This specialization is not present in the book. It makes it easier to define
|
||||
// Visitors for multiple types in a shot by using a typelist. Example:
|
||||
//
|
||||
// class SomeVisitor :
|
||||
// public BaseVisitor // required
|
||||
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
|
||||
// public Visitor<Paragraph>
|
||||
// {
|
||||
// public:
|
||||
// void Visit(RasterBitmap&); // visit a RasterBitmap
|
||||
// void Visit(Paragraph &); // visit a Paragraph
|
||||
// };
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Private
|
||||
{
|
||||
// helper for Visitor's the left base class
|
||||
template <unsigned int ListId>
|
||||
struct VisitorImplLeft
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
// helper for Visitor's the right base class
|
||||
template <unsigned int ListId>
|
||||
struct VisitorImplRight
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
// simulates specialization
|
||||
// class Visitor<Head, R>
|
||||
template <>
|
||||
struct VisitorImplLeft<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class T, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
typedef R ReturnType;
|
||||
virtual ReturnType Visit(T&) = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// simulates the left base class for the specialization
|
||||
// class Visitor<Typelist<Head, Tail>, R>
|
||||
template <>
|
||||
struct VisitorImplLeft<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef Visitor<typename TList::Head, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::NoneList_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
// simulates the right base class for the specialization
|
||||
// class Visitor<Typelist<Head, Tail>, R>
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
typedef Visitor<typename TList::Tail, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VisitorImplRight<TL::Private::AtomList_ID>
|
||||
{
|
||||
template <class TList, class R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
// MSVC 6.0 will complain if we try to let Visitor inherit
|
||||
// directly from VisitorImplLeft/VisitorImplRight
|
||||
template <class T, class R>
|
||||
struct VisitorImplLeftWrap
|
||||
{
|
||||
struct Dummy{};
|
||||
typedef typename VisitorImplLeft
|
||||
<
|
||||
TL::Private::IsTypelist<T>::type_id == TL::Private::AtomList_ID ?
|
||||
TL::Private::Typelist_ID :
|
||||
TL::Private::IsTypelist<T>::type_id
|
||||
>::template In<T, R>::Result TempType;
|
||||
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
struct VisitorImplRightWrap
|
||||
{
|
||||
struct Dummy{};
|
||||
typedef typename VisitorImplRight
|
||||
<
|
||||
TL::Private::IsTypelist<T>::type_id
|
||||
>::template In<T, R>::Result TempType;
|
||||
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
template <class T, typename R>
|
||||
class Visitor : public Private::VisitorImplLeftWrap<T, R>::Result,
|
||||
public Private::VisitorImplRightWrap<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 = int /* = void */ > class BaseVisitorImpl;
|
||||
|
||||
// class for the void-case
|
||||
template <class TList> class BaseVisitorImplVoid;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <unsigned int ListTag>
|
||||
struct BaseVisitorImplHelper
|
||||
{
|
||||
template <typename T, typename R>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BaseVisitorImplHelper<TL::Private::Typelist_ID>
|
||||
{
|
||||
template <typename TList, typename R>
|
||||
struct In
|
||||
{
|
||||
typedef typename Loki::Select<
|
||||
IsVoid<R>::value,
|
||||
BaseVisitorImplVoid<TList>,
|
||||
BaseVisitorImpl<TList, R>
|
||||
>::Result Result;
|
||||
//typedef BaseVisitorImpl<TList, R> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct BaseVisitorImplHelper<TL::Private::NullType_ID>
|
||||
{
|
||||
template <typename TList, typename R>
|
||||
struct In
|
||||
{
|
||||
struct Result {};
|
||||
};
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
struct BaseVisitorImplWrap
|
||||
{
|
||||
struct Dummy {};
|
||||
typedef typename BaseVisitorImplHelper
|
||||
<
|
||||
TL::Private::IsTypelist<typename T::Tail>::
|
||||
type_id == TL::Private::AtomList_ID ?
|
||||
TL::Private::Typelist_ID :
|
||||
TL::Private::IsTypelist<typename T::Tail>::type_id
|
||||
>::template In<typename T::Tail, R>::Result TempType;
|
||||
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
||||
typedef Workaround::LeftBase Result;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <class TList, typename R>
|
||||
class BaseVisitorImpl : public Visitor<typename TList::Head, R>,
|
||||
public Private::BaseVisitorImplWrap<TList, R>::Result
|
||||
{
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
public:
|
||||
// using BaseVisitorImpl<Tail, R>::Visit;
|
||||
|
||||
virtual R Visit(typename TList::Head&)
|
||||
{ return R(); }
|
||||
};
|
||||
|
||||
// class for the void-case
|
||||
template <class TList>
|
||||
class BaseVisitorImplVoid : public Visitor<typename TList::Head, void>,
|
||||
public Private::BaseVisitorImplWrap<TList, void>::Result
|
||||
{
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
public:
|
||||
// using BaseVisitorImpl<Tail, R>::Visit;
|
||||
|
||||
virtual void Visit(typename TList::Head&)
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultCatchAll
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename R, typename Visited>
|
||||
struct DefaultCatchAll
|
||||
{
|
||||
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
||||
{ return R(); }
|
||||
};
|
||||
|
||||
// template template parameter workaround.
|
||||
// use Wrapper-Classes like this to instantiate BaseVisitable
|
||||
struct DefaultCatchAllWrapper
|
||||
{
|
||||
template <class R, class Visited>
|
||||
struct In
|
||||
{
|
||||
typedef DefaultCatchAll<R, Visited> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename R, typename Visited>
|
||||
struct DefaultCatchAllVoid
|
||||
{
|
||||
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
||||
{}
|
||||
};
|
||||
|
||||
struct DefaultCatchAllVoidWrapper
|
||||
{
|
||||
template <class R, class Visited>
|
||||
struct In
|
||||
{
|
||||
typedef DefaultCatchAllVoid<R, Visited> type;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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();
|
||||
}
|
||||
};
|
||||
|
||||
struct NonStrictVisitorUnitWrapper
|
||||
{
|
||||
template <class T, class B>
|
||||
struct In
|
||||
{
|
||||
typedef NonStrictVisitorUnit<T, B> type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class TList, typename R = int /* = void */>
|
||||
class NonStrictVisitor
|
||||
: public GenLinearHierarchy<
|
||||
TList,
|
||||
NonStrictVisitorUnitWrapper,
|
||||
Visitor<TList, R> >
|
||||
{
|
||||
};
|
||||
|
||||
template <class T, class Base>
|
||||
struct NonStrictVisitorUnitVoid : public Base
|
||||
{
|
||||
typedef void ReturnType;
|
||||
ReturnType Visit(T&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct NonStrictVisitorUnitVoidWrapper
|
||||
{
|
||||
template <class T, class B>
|
||||
struct In
|
||||
{
|
||||
typedef NonStrictVisitorUnitVoid<T, B> type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class TList>
|
||||
class NonStrictVisitorVoid
|
||||
: public GenLinearHierarchy<
|
||||
TList,
|
||||
NonStrictVisitorUnitVoidWrapper,
|
||||
Visitor<TList, void> >
|
||||
{
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template BaseVisitable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
typename R = int/* = void */,
|
||||
class CatchAll = DefaultCatchAllWrapper
|
||||
>
|
||||
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)
|
||||
{
|
||||
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
|
||||
// Apply the Acyclic Visitor
|
||||
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
|
||||
{
|
||||
return p->Visit(visited);
|
||||
}
|
||||
return CatchA::OnUnknownVisitor(visited, guest);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// class for the void-case
|
||||
template
|
||||
<
|
||||
class CatchAll = DefaultCatchAllVoidWrapper
|
||||
>
|
||||
class BaseVisitableVoid
|
||||
{
|
||||
public:
|
||||
typedef void ReturnType;
|
||||
virtual ~BaseVisitableVoid() {}
|
||||
virtual ReturnType Accept(BaseVisitor&) = 0;
|
||||
|
||||
protected: // give access only to the hierarchy
|
||||
template <class T>
|
||||
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
||||
{
|
||||
typedef ApplyInnerType2<CatchAll, void, T>::type CatchA;
|
||||
// Apply the Acyclic Visitor
|
||||
if (Visitor<T, void>* p = dynamic_cast<Visitor<T, void>*>(&guest))
|
||||
{
|
||||
p->Visit(visited);
|
||||
}
|
||||
CatchA::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(Loki::BaseVisitor& guest) \
|
||||
{ return AcceptImpl(*this, guest); }
|
||||
|
||||
#define DEFINE_VISITABLE_VOID() \
|
||||
virtual void Accept(Loki::BaseVisitor& guest) \
|
||||
{ AcceptImpl(*this, guest); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CyclicVisitor
|
||||
// Put it in every class that you want to make visitable (in addition to
|
||||
// deriving it from BaseVisitable<R>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename R, class TList>
|
||||
class CyclicVisitor : public Visitor<TList, R>
|
||||
{
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
// using Visitor<TList, R>::Visit;
|
||||
|
||||
template <class Visited>
|
||||
ReturnType GenericVisit(Visited& host)
|
||||
{
|
||||
Visitor<Visited, ReturnType>& subObj = *this;
|
||||
return subObj.Visit(host);
|
||||
}
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
class CyclicVisitorVoid : public Visitor<TList, void>
|
||||
{
|
||||
public:
|
||||
typedef void ReturnType;
|
||||
// using Visitor<TList, R>::Visit;
|
||||
|
||||
template <class Visited>
|
||||
ReturnType GenericVisit(Visited& host)
|
||||
{
|
||||
Visitor<Visited, ReturnType>& subObj = *this;
|
||||
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); }
|
||||
|
||||
#define DEFINE_CYCLIC_VISITABLE_VOID(SomeVisitor) \
|
||||
virtual void Accept(SomeVisitor& guest) \
|
||||
{ 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!!!
|
||||
// Oct 27, 2002: ported by Benjamin Kaufmann to MSVC 6.0
|
||||
// Feb 23, 2003: Removed superfluous implementation classes and added Loki::
|
||||
// qualification to Accept's Paramter (in the macro) B.K.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // VISITOR_INC_
|
||||
|
708
include/noncc/MSVC/1200/readme.txt
Executable file
708
include/noncc/MSVC/1200/readme.txt
Executable file
|
@ -0,0 +1,708 @@
|
|||
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
|
||||
-------------------------------------------------------------------
|
||||
Version: 0.5e
|
||||
|
||||
Introduction/Compatibility:
|
||||
---------------------------
|
||||
This is a partial MSVC 6.0 Sp5 compatible port of Andrei Alexandrescu's excellent Loki Library.
|
||||
Because I could not retain the originial interface in all places, this port is not
|
||||
compatible to the original library and therefore code using this port *cannot* generally be
|
||||
used together with the original lib.
|
||||
This is, of course, a great pity.
|
||||
So if you know of a complete and full interface-compatible VC 6.0
|
||||
port or if you know how to improve this port, please let me know.
|
||||
|
||||
Contact:
|
||||
--------
|
||||
For any suggestions, bug reports, comments and questions please email me to
|
||||
Hume@c-plusplus.de
|
||||
|
||||
Using this port:
|
||||
----------------
|
||||
To use this port, 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.
|
||||
|
||||
Fixes:
|
||||
------
|
||||
Mar 18, 2004:
|
||||
-------------
|
||||
* In SmartPtr.h: Added operator=-workaround for pointer-assignment
|
||||
* In Functor.h: Changed value parameter to reference parameter
|
||||
in FunctorBase and FunctorVoidBase Ctors.
|
||||
Mar 21, 2003:
|
||||
-------------
|
||||
* In MultiMethods.h: Added a new explicit template argument specification (ETAS)-workaround
|
||||
for FnDispatcher::Add which is more compliant with other
|
||||
ETAS-workarounds used in this port.
|
||||
|
||||
Mar 20, 2003:
|
||||
-------------
|
||||
* In MultiMethods.h: Fixed bugs in FnDispatcher and FunctorDispatcher.
|
||||
Fixing FnDispatcher led to an Interface change (see section "Interface changes").
|
||||
|
||||
Mar 08, 2003:
|
||||
-------------
|
||||
* In HierarchyGenerators.h: implemented transparent workaround for
|
||||
'explicit template argument specification for nonmeber functions'-bug.
|
||||
The Field-Functions can now be called as in the original lib.
|
||||
|
||||
Mar 06, 2003:
|
||||
-------------
|
||||
* In SmartPointer.h: Added helper-macros for convenient specialization
|
||||
of std::less for Smart-Pointers.
|
||||
|
||||
* I found a way to use void as a default value for template parameters.
|
||||
Therefore I changed MultiMethods.h and Visitor.h accordingly.
|
||||
|
||||
|
||||
Feb 2003:
|
||||
---------
|
||||
* created new versions of Functor.h, Visitor.h and MultiMethods.h that
|
||||
now can handle void return types transparently.
|
||||
|
||||
* ported SmartPtr's Ownership-Policy RefCountedMT
|
||||
|
||||
* Added isFunctionPointer to TypeTraits.
|
||||
|
||||
* Replaced all pointer-type dummy-parameters needed as a workaround
|
||||
for VC's 'explicit template argument specification'-bug with Typ2Type-dummy
|
||||
parameters.
|
||||
|
||||
* fixed the problems with BindFirst (Functor.h) that led to
|
||||
C1001-Internal compiler errors.
|
||||
|
||||
* fixed numerous other bugs.
|
||||
|
||||
|
||||
Jan 30, 2003:
|
||||
-------------
|
||||
* In TypeTraits.h: Fixed bugs in TypeTraits' scalar and array detection.
|
||||
const and volatile detection is now based on techniques from boost's type traits
|
||||
(see http://www.boost.org/libs/type_traits/)
|
||||
Added Enum- and pointer-to-member-function-detection code.
|
||||
Thanks to M. Yamada.
|
||||
|
||||
|
||||
Jan 12, 2003:
|
||||
-------------
|
||||
* changed the signature of SmallObject's op new. Now it
|
||||
matches the corresponding op delete.
|
||||
Thanks to M.Yamada for the hint and the solution.
|
||||
|
||||
Dec 08, 2002:
|
||||
-------------
|
||||
* In HierarchyGenerators.h: Sergey Khachatrian reported a bug
|
||||
in GenScatterHierarchy when used with a typelist containing
|
||||
equal types (e.g. GenScatterHierarchy<TYPELIST_2(int, int), UnitWrapper>
|
||||
resp. Tuple<TYPELIST_2(int, int)>)
|
||||
Fixing the bug I found another MSVC6-Problem in the Field-function.
|
||||
The workaround for this problems results in an interface change.
|
||||
|
||||
please refer to the section "Interface changes" below for further information.
|
||||
|
||||
Dec 03, 2002
|
||||
-------------
|
||||
* In MSVC6Helpers.h: The original version failed to qualify some types from the
|
||||
Private-Namespace.
|
||||
Thanks to Adi Shavit for pointing that out
|
||||
|
||||
* In Threads.h: Changed wrong ctor/dtor names in ObjectLevelLockable.
|
||||
Thanks to Adi Shavit for pointing that out
|
||||
|
||||
Nov 19, 2002:
|
||||
-------------
|
||||
* In SmartPtr.h: Changed template ctors. See Notes.
|
||||
|
||||
Notes:
|
||||
------
|
||||
The original Loki Lib uses some pretty advanced (resp. new) C++ features like:
|
||||
|
||||
A. partial template specialization.
|
||||
B. template template parameters.
|
||||
C. explicit template argument specification for member- and nonmeber functions.
|
||||
D. covariant return types.
|
||||
E. Template parameters with default type void
|
||||
F. return statements with an expression of type cv void in functions with a return type of cv void.
|
||||
|
||||
Unfortunately the MSVC 6.0 supports neither of them.
|
||||
|
||||
A. I used various techniques to simulate partial template specialization. In some cases
|
||||
these techniques allowed me to retain the original interfaces but often that was not
|
||||
possible (or better: i did not find a proper solution). In any case it led
|
||||
to increasing code complexity :-)
|
||||
|
||||
B. One way to simulate template template parameters is to replace the template class with
|
||||
a normal class containing a nested template class. You then move the original functionality
|
||||
to the nested class.
|
||||
The problem with this approach is MSVC's 'dependent template typedef bug'.
|
||||
MSVC 6.0 does not allow something like this:
|
||||
|
||||
[code]
|
||||
template <class APolicy, class T>
|
||||
struct Foo
|
||||
{
|
||||
// error C2903: 'In' : symbol is neither a class template nor a function template
|
||||
typedef typename APolicy::template In<T> type;
|
||||
};
|
||||
[/code]
|
||||
|
||||
To make a long story short, I finally decided to use boost::mpl's apply-technique to
|
||||
simulate template template parameters. This approach works fine with MSVC 6.0. But be warned,
|
||||
this technique uses not valid C++.
|
||||
Of course, replacing template template parameters always results in some interface changes.
|
||||
|
||||
C. I added dummy-Parameters to (Member-)Functions that depend on explicit template
|
||||
argument specification. These dummy-Parameters help the compiler in deducing the template
|
||||
parameters that otherwise need to be explicitly specified.
|
||||
Example:
|
||||
[code]
|
||||
struct Foo
|
||||
{
|
||||
template <class T>
|
||||
T Func();
|
||||
};
|
||||
[/code]
|
||||
becomes
|
||||
[code]
|
||||
struct Foo
|
||||
{
|
||||
template <class T>
|
||||
T Func(Type2Type<T>);
|
||||
};
|
||||
[/code]
|
||||
in this port.
|
||||
|
||||
Update:
|
||||
-------
|
||||
The MSVC 6.0 sometimes does not overload normal functions depending
|
||||
on explicit argument specification correctly (see: Microsoft KB Article - 240871)
|
||||
The following code demonstrates the problem:
|
||||
[code]
|
||||
template <unsigned i, class T>
|
||||
void BugDemonstration(T p)
|
||||
{
|
||||
printf("BugDemonstration called with i = %d\n", i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
GenScatterHierarchy<TYPELIST_3(int, int, int), TestUnitWrapper> Bla;
|
||||
// will always print: "BugDemonstration called with i = 2";
|
||||
BugDemonstration<0>(Bla);
|
||||
BugDemonstration<1>(Bla);
|
||||
BugDemonstration<2>(Bla);
|
||||
}
|
||||
[/code]
|
||||
|
||||
Fortunately there is a transparent workaround for this problem. Simply add
|
||||
a dummy-parameter with a proper default value:
|
||||
[code]
|
||||
template <unsigned i, class T>
|
||||
void BugDemonstration(T p, Int2Type<i>* = (Int2Type<i>*)0)
|
||||
{
|
||||
printf("BugDemonstration called with i = %d\n", i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
GenScatterHierarchy<TYPELIST_3(int, int, int), TestUnitWrapper> Bla;
|
||||
// will now work correctly
|
||||
BugDemonstration<0>(Bla);
|
||||
BugDemonstration<1>(Bla);
|
||||
BugDemonstration<2>(Bla);
|
||||
}
|
||||
[/code]
|
||||
|
||||
Unfortunately adding dummy-parameters does not always work.
|
||||
For example for one of FnDispatcher's Add-member-functions you have to explicitly
|
||||
specify two type- and one non-type parameter.
|
||||
[code]
|
||||
template </*...*/typename ResultType/*...*/>
|
||||
class FnDispatcher
|
||||
{
|
||||
public:
|
||||
//...
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&)>
|
||||
void Add(){/*...*/}
|
||||
};
|
||||
//...
|
||||
FnDispatcher<Shape> dis;
|
||||
dis.Add<Poly, Poly, &AFunc>();
|
||||
[/code]
|
||||
Using dummy-parameters as workaround FnDispatcher::Add would become something
|
||||
like this:
|
||||
[code]
|
||||
template<class S1, class S2, class R, R (*)(S1&,S2&)>
|
||||
struct Helper {};
|
||||
|
||||
template </*...*/typename ResultType/*...*/>
|
||||
class FnDispatcher
|
||||
{
|
||||
public:
|
||||
//...
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&)>
|
||||
void Add(Helper<SomeLhs, SomeRhs, ResultType, callback>)
|
||||
{}
|
||||
};
|
||||
//...
|
||||
FnDispatcher<void> f;
|
||||
f.Add(Helper<Rectangle, Rectangle, void, &Func>());
|
||||
[/code]
|
||||
This compiles fine, but alas Add never gets called. I don't know what happens,
|
||||
I only know that the MSVC 6.0 won't generate code for a function call.
|
||||
|
||||
In situations like that, instead of dummy-Parameters I used nested template-classes
|
||||
with overloaded function-operator as a workaround.
|
||||
[code]
|
||||
template </*...*/typename ResultType/*...*/>
|
||||
class FnDispatcher
|
||||
{
|
||||
public:
|
||||
// the member-function Add becomes a member-template-class
|
||||
// with overloaded function operator.
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&)>
|
||||
struct AddI
|
||||
{
|
||||
void operator()(FnDispatcher<ResultType>& o) {/*...*/}
|
||||
};
|
||||
};
|
||||
//...
|
||||
FnDispatcher<void> f;
|
||||
FnDispatcher<void>::AddI<Rectangle, Rectangle, &Func>()(f);
|
||||
[/code]
|
||||
|
||||
If you know of a better workaround, please let me know.
|
||||
|
||||
Update:
|
||||
-------
|
||||
The problem in the example above is Add's nontype-function-pointer-Parameter.
|
||||
If one changes this parameter to a type-parameter the problem vanishes.
|
||||
The example above then becomes:
|
||||
[code]
|
||||
template </*...*/typename ResultType/*...*/>
|
||||
class FnDispatcher
|
||||
{
|
||||
public:
|
||||
// Etas stands for explicit template argument specification.
|
||||
// Do whatever you need to do with callback in this class.
|
||||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false>
|
||||
struct Etas
|
||||
{/*...*/};
|
||||
|
||||
// EtasType has to be a template parameter. If one tries to use
|
||||
// a parameter of type Etas the MSVC 6.0 won't generate correct
|
||||
// code.
|
||||
template <class EtasType>
|
||||
void Add(EtasType EtasObj)
|
||||
{/*...*/}
|
||||
};
|
||||
//...
|
||||
typedef FnDispatcher<void> DisType;
|
||||
DisType f;
|
||||
f.Add(DisType::Etas<Rectangle, Rectangle, &Func>());
|
||||
[/code]
|
||||
|
||||
The port provides both workarounds but the use of the second should be preferred,
|
||||
because it betters fits to the rest of the port's workarounds.
|
||||
|
||||
D. Virtual functions that use covariant return types (e.g. return a pointer to Derived)
|
||||
in the original library were changed so that they have exactly the
|
||||
same return type as the original virtual function (e.g. return a pointer to Base).
|
||||
|
||||
E. The MSVC 6.0 does not allow code like this:
|
||||
[code]
|
||||
// error C2182: '__formal' illegal use of type 'void'
|
||||
template <class T, class R = void>
|
||||
struct Blub {};
|
||||
[/code]
|
||||
|
||||
Interestingly enough you can have void as default type by simply using another
|
||||
level of indirection:
|
||||
[code]
|
||||
struct VoidWrap
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <class T, class R = VoidWrap::type>
|
||||
struct Blub
|
||||
{};
|
||||
[/code]
|
||||
|
||||
F. To workaround void returns I did the following:
|
||||
From every original class I moved those functions that potentially
|
||||
produce void returns to new classes. One for the general case and
|
||||
one for the void case.
|
||||
In the class for the general case I implemented the functions in the original way.
|
||||
In the class for the void case I removed the return statements and therefore the
|
||||
potential void return.
|
||||
Depending on the return type, the original class inherits from the
|
||||
corresponding new class and thus gets the proper implementation of
|
||||
the previously removed functions.
|
||||
|
||||
For example:
|
||||
[code]
|
||||
template <class R> struct Foo
|
||||
{
|
||||
R Func() { return R(); }
|
||||
};
|
||||
[/code]
|
||||
becomes:
|
||||
[code]
|
||||
namespace Private
|
||||
{
|
||||
template <class R> struct FooBase
|
||||
{
|
||||
R Func() {return R();}
|
||||
};
|
||||
struct FooVoidBase
|
||||
{
|
||||
typedef void R;
|
||||
R Func() {}
|
||||
};
|
||||
}
|
||||
template <class R>
|
||||
struct Foo : public Select<IsVoid<R>::value, FooVoidBase, FooBase<R> >::Result
|
||||
{};
|
||||
[/code]
|
||||
|
||||
The MSVC 6 allows explicit template specialization in class scope.
|
||||
In contrast the C++ Standards only allows explicit template specialization
|
||||
in namespace scope. Using the non-compliant feature, the implementation
|
||||
of the example above becomes a little less complicated:
|
||||
[code]
|
||||
namespace Private
|
||||
{
|
||||
struct FooBase
|
||||
{
|
||||
template <class R>
|
||||
struct In
|
||||
{
|
||||
R Func() {return R();}
|
||||
};
|
||||
template <>
|
||||
struct In<void>
|
||||
{;
|
||||
void Func() {}
|
||||
};
|
||||
};
|
||||
}
|
||||
template <class R>
|
||||
struct Foo : Private::FooBase::In<R>
|
||||
{};
|
||||
[/code]
|
||||
|
||||
Please note that *all* new base classes are only meant as a hidden
|
||||
implementation detail.
|
||||
You should never use any of them directly or indirectly. In particular don't
|
||||
make use of the possible derived-to-base conversion.
|
||||
|
||||
In the old version of Functor.h I changed a ResultType of type void to
|
||||
VoidAsType (an udt). This change is transparent to the user of Functor.
|
||||
|
||||
Some words to template-ctors resp. template assignment operators:
|
||||
The MSVC 6.0 introduces an order-dependency for template ctor
|
||||
resp. template assignemt operators.
|
||||
If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
|
||||
you *must* write the templated version first.
|
||||
So instead of
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
Foo(const Foo&)
|
||||
{}
|
||||
template <class U>
|
||||
Foo(const Foo<U>& r)
|
||||
{}
|
||||
};
|
||||
[/code]
|
||||
you *need* to write:
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
template <class U>
|
||||
Foo(const Foo<U>& r)
|
||||
{}
|
||||
|
||||
Foo(const Foo& r)
|
||||
{}
|
||||
};
|
||||
[/code]
|
||||
|
||||
Many thanks to Nelson Elói for pointing that out and for providing me
|
||||
with this solution.
|
||||
|
||||
The above solution unfortunately does not work if the template ctor does not have
|
||||
the form of a copy-ctor. If you write something like this (as in the functor-class):
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
template <class Fun>
|
||||
Foo(Fun r)
|
||||
{}
|
||||
|
||||
Foo(const Foo& r)
|
||||
{}
|
||||
};
|
||||
[/code]
|
||||
then the VC will no longer find a copy-ctor.
|
||||
|
||||
Because of this, i can't use Nelson Elói's solution in Functor.h
|
||||
|
||||
Interface changes:
|
||||
------------------
|
||||
1. In Threads.h:
|
||||
|
||||
* Thread-Policies changed from class templates to normal classes containing a
|
||||
nested class template 'In'.
|
||||
|
||||
consequences:
|
||||
This change is not very dramatic because it won't break code using this port when
|
||||
switching to the original library (only new Thread-Policies must be changed)
|
||||
|
||||
2. In Singleton.h:
|
||||
|
||||
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
|
||||
Member-Templates.
|
||||
|
||||
consequences:
|
||||
Again this change will only break new Policies when switching to the
|
||||
original library.
|
||||
|
||||
3. In Functor.h:
|
||||
|
||||
* No covariant return types.
|
||||
|
||||
consequences:
|
||||
DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return
|
||||
type and ThreadingModel its current ThreadingModel.
|
||||
|
||||
4. TypeTraits.h
|
||||
|
||||
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class
|
||||
fails to provide the following typedefs:
|
||||
PointeeType, ReferredType, NonVolatileType and UnqualifiedType.
|
||||
|
||||
* Since the VC 6 does not differentiate
|
||||
between void, const void, volatile void and const volatile void the following
|
||||
assertions will fail:
|
||||
assert(TypeTraits<const void>::isConst == 1)
|
||||
assert(TypeTraits<volatile void>::isVolatile == 1)
|
||||
assert(TypeTraits<const volatile void>::isConst == 1)
|
||||
assert(TypeTraits<const volatile void>::isVolatile == 1)
|
||||
|
||||
* This port adds isEnum, isMemberFunctionPointer and isFunctionPointer.
|
||||
|
||||
|
||||
5. HierarchyGenerator.h
|
||||
|
||||
* I used Mat Marcus' approach to port GenScatterHierarchy.
|
||||
See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences.
|
||||
|
||||
* Same for GenLinearHierarchy
|
||||
|
||||
* Unit is no longer a template template parameter.
|
||||
|
||||
consequences:
|
||||
For every concrete unit-template there must be a normal class containing
|
||||
a nested-template class called 'In'. 'In' should only contain a typedef to the
|
||||
concrete Unit.
|
||||
|
||||
Update:
|
||||
The port's original version of GenScatterHierarchy does not work when used
|
||||
with typelists containing equal types.
|
||||
The problem is due to a VC bug. The VC fails to compile code similar
|
||||
to this, although it is perfectly legal.
|
||||
[code]
|
||||
template <class T>
|
||||
class Wrapper
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct B : public Wrapper<T>
|
||||
{};
|
||||
|
||||
// ERROR: 'A<T>' : direct base 'Wrapper<T>' is inaccessible; already a base of 'B<T>'
|
||||
template <class T>
|
||||
class A : public B<T>, public Wrapper<T>
|
||||
{};
|
||||
[/code]
|
||||
|
||||
Unfortunately my workaround has a big drawback.
|
||||
GenScatterHierarchy now has to generate a lot more classes.
|
||||
Alexandrescu's original implementation generates 3*n classes (n - number of types in the typelist)
|
||||
The old version of my port creates 4 * n + 1
|
||||
The new version will create 5 * n
|
||||
|
||||
The fix also reveals the "Explicitly Specified Template Functions Not Overloaded Correctly"-Bug
|
||||
(Microsoft KB Article - 240871) in the Field-Function taking a nontype int Parameter.
|
||||
See Notes (section C) for the description of the workaround.
|
||||
|
||||
I also added a macro FIELD. Using this macro one can write
|
||||
FIELD(obj, 0)
|
||||
|
||||
|
||||
6. Factory.h
|
||||
|
||||
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter.
|
||||
Use a class with member-templates instead.
|
||||
|
||||
consequences:
|
||||
This change will only break new Policies when switching to the
|
||||
original library.
|
||||
|
||||
7. AbstractFactory.h
|
||||
|
||||
* no covariant return types
|
||||
|
||||
* no template template parameters
|
||||
For every concrete Factory-Unit there must be a normal class containing
|
||||
a nested-template class called 'In'. 'In' shall contain a typedef to the
|
||||
concrete Factory-Unit.
|
||||
|
||||
* Added a dummy-Parameter to AbstractFactory::Create (see C.)
|
||||
Calling syntax changed from:
|
||||
ConcProduct* p = aFactory.Create<ConcProduct>();
|
||||
to
|
||||
ConcProduct* p = aFactory.Create(Type2Type<ConcProduct>());
|
||||
|
||||
|
||||
8. SmartPtr.h
|
||||
|
||||
* no template template parameters.
|
||||
(see 7.for a description of the consequences)
|
||||
|
||||
* This port does not specialize std::less
|
||||
|
||||
Update:
|
||||
-------
|
||||
The port provides some helper-macros for convenient specialization
|
||||
of std::less for Smart-Pointers.
|
||||
|
||||
If, for example, you want to use a Smart-Pointer as the key of a std::map,
|
||||
you can do it like this:
|
||||
[code]
|
||||
#include <map>
|
||||
#include <loki/SmartPtr.h>
|
||||
|
||||
SMARTPTR_SPECIALIZE_LESS(Apple)
|
||||
|
||||
class Apple {};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::map<SmartPointer<Apple>, int> m;
|
||||
//...
|
||||
}
|
||||
[/code]
|
||||
|
||||
9. Visitor.h
|
||||
|
||||
* no template template parameters
|
||||
(see 7.for a description of the consequences)
|
||||
|
||||
* This port fails to correctly support void return types. As a workaround it provides
|
||||
a set of complete new classes (and macros) for void. Default arguments of type void
|
||||
were replaced by arguments of type int.
|
||||
|
||||
Update:
|
||||
-------
|
||||
In the new version of Visitor.h there are no longer extra classes for void.
|
||||
Instead the original classes are now able to handle the return type void.
|
||||
However there are still two sets of macros. One for return type = void
|
||||
(DEFINE_VISITABLE_VOID, DEFINE_CYCLIC_VISITABLE_VOID) and one for return
|
||||
type != void (DEFINE_VISITABLE, DEFINE_CYCLIC_VISITABLE)
|
||||
|
||||
|
||||
10. MultiMethods.h
|
||||
|
||||
* replaced all template template parameters with 'normal' parameters (see 7.
|
||||
for a description of the consequences)
|
||||
|
||||
* This port does not support functions with return type void.
|
||||
|
||||
* dummy parameters were added to functions that otherwise would depend on
|
||||
explicit template argument specification (14.8.1).
|
||||
|
||||
Update:
|
||||
-------
|
||||
* The port now supports functions with return type void.
|
||||
|
||||
Some words to BasicDispatcher:
|
||||
------------------------------
|
||||
You can't use a (namespace level) template function as callback-function
|
||||
for BasicDispatcher. This is because using the VC 6.0 you can't explicity
|
||||
specify the template-paramters when adding the concrete function instance
|
||||
to the dispatcher.
|
||||
Normaly you can write something like this:
|
||||
[code]
|
||||
template <class DerivedShape1, class DerivedShape2>
|
||||
int HatchShapes(Shape&, Shape&) {...}
|
||||
|
||||
typedef ::Loki::BasicDispatcher<Shape> Dispatcher;
|
||||
|
||||
void Func(Dispatcher& x)
|
||||
{
|
||||
x.Add(&HatchShapes<Circle, Rectangle>);
|
||||
}
|
||||
[/code]
|
||||
Using the VC 6.0 this is not possible, because there is no
|
||||
way to specify the types for DerivedShape1 and DerivedShape2 (at least
|
||||
I know of no way).
|
||||
|
||||
As a workaround use a helper-template class in conjunction with
|
||||
a static member function:
|
||||
[code]
|
||||
template <class DerivedShape1, class DerivedShape2>
|
||||
struct Hatch_Helper
|
||||
{
|
||||
int HatchShapes(Shape&, Shape&) {...}
|
||||
};
|
||||
|
||||
typedef ::Loki::BasicDispatcher<Shape> Dispatcher;
|
||||
|
||||
void Func(Dispatcher& x)
|
||||
{
|
||||
x.Add(&Hatch_Helper<Circle, Rectangle>::HatchShapes);
|
||||
}
|
||||
[/code]
|
||||
Some words to FnDispatcher:
|
||||
---------------------------
|
||||
The trampoline-Versions of FnDispatcher::Add differ
|
||||
from the original library.
|
||||
|
||||
Using the original library one writes:
|
||||
[code]
|
||||
typedef FnDispatcher<Shape> Dispatcher;
|
||||
void Hatch(Rectangle& lhs, Poly& rhs) {...}
|
||||
|
||||
Dispatcher dis;
|
||||
disp.Add<Rectangle, Poly, &Hatch>();
|
||||
[/code]
|
||||
|
||||
Using this port the last line either becomes:
|
||||
[code]
|
||||
disp.Add(Dispatcher::Etas<Rectangle, Poly, &Hatch>());
|
||||
[/code]
|
||||
or
|
||||
[code]
|
||||
Dispatcher::AddI<Rectangle, Poly, &Hatch>()(dis);
|
||||
[/code]
|
||||
|
||||
More info:
|
||||
----------
|
||||
The original Loki library can be found here: http://moderncppdesign.com
|
||||
For Rani Sharoni's VC 7.0 port see: http://www.geocities.com/rani_sharoni/LokiPort.html
|
||||
|
63
include/noncc/MSVC/1200/static_check.h
Executable file
63
include/noncc/MSVC/1200/static_check.h
Executable file
|
@ -0,0 +1,63 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef STATIC_CHECK_INC_
|
||||
#define STATIC_CHECK_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper structure for the STATIC_CHECK macro
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int> struct CompileTimeError;
|
||||
template<> struct CompileTimeError<true> {};
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template<int x> struct static_assert_test{};
|
||||
template <bool x> struct SizeError;
|
||||
|
||||
template <> struct SizeError<true>{};
|
||||
}
|
||||
}
|
||||
|
||||
#define STATIC_SIZE_ASSERT(Type, ExpSize) \
|
||||
typedef ::Loki::Private::static_assert_test<sizeof(::Loki::Private::SizeError \
|
||||
< (bool) (sizeof(Type) == ExpSize) >)> static_assert_typedef_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro STATIC_CHECK
|
||||
// Invocation: STATIC_CHECK(expr, id)
|
||||
// where:
|
||||
// expr is a compile-time integral or pointer expression
|
||||
// id is a C++ identifier that does not need to be defined
|
||||
// If expr is zero, id will appear in a compile-time error message.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define STATIC_CHECK(expr, msg) \
|
||||
{ Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
|
||||
// definition
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // STATIC_CHECK_INC_
|
167
include/noncc/MSVC/1300/AbstractFactory.h
Executable file
167
include/noncc/MSVC/1300/AbstractFactory.h
Executable file
|
@ -0,0 +1,167 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef ABSTRACTFACTORY_INC_
|
||||
#define ABSTRACTFACTORY_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeManip.h"
|
||||
#include "HierarchyGenerators.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactoryUnit
|
||||
// The building block of an Abstract Factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class AbstractFactoryUnit
|
||||
{
|
||||
public:
|
||||
virtual T* DoCreate(Type2Type<T>) = 0;
|
||||
virtual ~AbstractFactoryUnit() {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AbstractFactory
|
||||
// Defines an Abstract Factory interface starting from a typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
template <class> class Unit = AbstractFactoryUnit
|
||||
>
|
||||
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
|
||||
{
|
||||
public:
|
||||
typedef TList ProductList;
|
||||
|
||||
template <class T> T* Create()
|
||||
{
|
||||
Unit<T>& unit = *this;
|
||||
return unit.DoCreate(Type2Type<T>());
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template OpNewFactoryUnit
|
||||
// Creates an object by invoking the new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class OpNewFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
return new ConcreteProduct;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PrototypeFactoryUnit
|
||||
// Creates an object by cloning a prototype
|
||||
// There is a difference between the implementation herein and the one described
|
||||
// in the book: GetPrototype and SetPrototype use the helper friend
|
||||
// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
|
||||
// name hiding issues. Plus, GetPrototype takes a reference to pointer
|
||||
// instead of returning the pointer by value.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class ConcreteProduct, class Base>
|
||||
class PrototypeFactoryUnit : public Base
|
||||
{
|
||||
typedef typename Base::ProductList BaseProductList;
|
||||
|
||||
protected:
|
||||
typedef typename BaseProductList::Tail ProductList;
|
||||
|
||||
public:
|
||||
typedef typename BaseProductList::Head AbstractProduct;
|
||||
|
||||
PrototypeFactoryUnit(AbstractProduct* p = 0)
|
||||
: pPrototype_(p)
|
||||
{}
|
||||
|
||||
friend void DoGetPrototype(const PrototypeFactoryUnit& me,
|
||||
AbstractProduct*& pPrototype)
|
||||
{ pPrototype = me.pPrototype_; }
|
||||
|
||||
friend void DoSetPrototype(PrototypeFactoryUnit& me,
|
||||
AbstractProduct* pObj)
|
||||
{ me.pPrototype_ = pObj; }
|
||||
|
||||
template <class U>
|
||||
void GetPrototype(U*& p)
|
||||
{ return DoGetPrototype(*this, p); }
|
||||
|
||||
template <class U>
|
||||
void SetPrototype(U* pObj)
|
||||
{ DoSetPrototype(*this, pObj); }
|
||||
|
||||
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
|
||||
{
|
||||
assert(pPrototype_);
|
||||
return pPrototype_->Clone();
|
||||
}
|
||||
|
||||
private:
|
||||
AbstractProduct* pPrototype_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConcreteFactory
|
||||
// Implements an AbstractFactory interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractFact,
|
||||
template <class, class> class Creator = OpNewFactoryUnit,
|
||||
class TList = typename AbstractFact::ProductList
|
||||
>
|
||||
class ConcreteFactory
|
||||
: public GenLinearHierarchy<
|
||||
typename TL::Reverse<TList>::Result, Creator, AbstractFact>
|
||||
{
|
||||
public:
|
||||
typedef typename AbstractFact::ProductList ProductList;
|
||||
typedef TList ConcreteProductList;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
// September 25, 2004: Fixed bug in PrototypeFactoryUnit::GetPrototype, thanks
|
||||
// to a bug report submitted by funcall.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ABSTRACTFACTORY_INC_
|
335
include/noncc/MSVC/1300/AssocVector.h
Executable file
335
include/noncc/MSVC/1300/AssocVector.h
Executable 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_
|
231
include/noncc/MSVC/1300/DataGenerators.h
Executable file
231
include/noncc/MSVC/1300/DataGenerators.h
Executable file
|
@ -0,0 +1,231 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Data Generator by Mr. Shannon Barber
|
||||
// This code DOES NOT accompany the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
//
|
||||
// Code covered by the MIT License
|
||||
//
|
||||
// The author makes no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Oct 10, 2002
|
||||
|
||||
#pragma once
|
||||
#include "Typelist.h"
|
||||
|
||||
//MSVC7 version
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IterateTypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace TL
|
||||
{
|
||||
template<typename T>
|
||||
struct nameof_type
|
||||
{
|
||||
const char* operator()()
|
||||
{
|
||||
return typeid(T).name();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct sizeof_type
|
||||
{
|
||||
size_t operator()()
|
||||
{
|
||||
return sizeof(T);
|
||||
}
|
||||
};
|
||||
template <class TList, template <typename> class UnitFunc>
|
||||
struct IterateTypes;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
// for some reason VC7 needs the base definition altough not in use
|
||||
template <typename TListTag>
|
||||
struct IterateTypesHelper1
|
||||
{
|
||||
template <typename T, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename TListTag>
|
||||
struct IterateTypesHelper2
|
||||
{
|
||||
template <typename T, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper1<TL::Typelist_tag>
|
||||
{
|
||||
template <class TList, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
typedef IterateTypes<typename TList::Head, GenFunc> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper2<TL::Typelist_tag>
|
||||
{
|
||||
template <class TList, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
typedef IterateTypes<typename TList::Tail, GenFunc> Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper1<TL::NoneList_tag>
|
||||
{
|
||||
template <typename AtomicType, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
typedef GenFunc<AtomicType> genfunc_t;
|
||||
template<class II>
|
||||
void operator()(II ii)
|
||||
{
|
||||
genfunc_t gen;
|
||||
//warning C4267: 'argument' : conversion from 'size_t' to 'const std::_Vbase', possible loss of data
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4267)
|
||||
//TODOSGB
|
||||
*ii = gen();
|
||||
#pragma warning(pop)
|
||||
++ii;
|
||||
}
|
||||
template<class II, class P1>
|
||||
void operator()(II ii, P1 p1)
|
||||
{
|
||||
genfunc_t gen;
|
||||
*ii = gen(p1);
|
||||
++ii;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper2<TL::NoneList_tag>
|
||||
{
|
||||
template <typename AtomicType, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
template<class II> void operator()(II) {}
|
||||
template<class II, class P1> void operator()(II, P1) {}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper1<TL::NullType_tag>
|
||||
{
|
||||
template <class TList, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
template<class II> void operator()(II) {}
|
||||
template<class II, class P1> void operator()(II, P1) {}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IterateTypesHelper2<TL::NullType_tag>
|
||||
{
|
||||
template <class TList, template <typename> class GenFunc>
|
||||
struct In
|
||||
{
|
||||
struct Result
|
||||
{
|
||||
template<class II> void operator()(II) {}
|
||||
template<class II, class P1> void operator()(II, P1) {}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Private
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IterateTypes
|
||||
// Iteratates a Typelist, and invokes the ctor of GenFunc<T>
|
||||
// for each type in the list, passing a functor along the way.
|
||||
// The functor is designed to be an insertion iterator which GenFunc<T>
|
||||
// can use to output information about the types in the list.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template <typename T, template <typename> class GenFunc>
|
||||
struct IterateTypes
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename Private::IterateTypesHelper1
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, GenFunc>::Result head_t;
|
||||
|
||||
typedef typename Private::IterateTypesHelper2
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, GenFunc>::Result tail_t;
|
||||
head_t head;
|
||||
tail_t tail;
|
||||
|
||||
template<class II>
|
||||
void operator()(II ii)
|
||||
{
|
||||
this->head.operator()(ii);
|
||||
this->tail.operator()(ii);
|
||||
}
|
||||
template<class II, class P1>
|
||||
void operator()(II ii, P1 p1)
|
||||
{
|
||||
this->head.operator()(ii, p1);
|
||||
this->tail.operator()(ii, p1);
|
||||
}
|
||||
};
|
||||
|
||||
//UnitFunc is really a template-template parameter, but MSVC7
|
||||
// chokes on the correct defintion. Oddly enough, it works correctly
|
||||
// with the 'undecorated' template parameter declaraion!
|
||||
//template <class> class UnitFunc
|
||||
template<typename Types, class UnitFunc, typename II>
|
||||
void iterate_types(II ii)
|
||||
{
|
||||
Loki::TL::IterateTypes<Types, UnitFunc> it;
|
||||
it(ii);
|
||||
}
|
||||
}//ns TL
|
||||
}//ns Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// Aug 17, 2002: Ported to MSVC7 by Rani Sharoni
|
||||
// Aug 18, 2002: Removed ctor(II), replaced with operator(II) Shannon Barber
|
||||
// Oct 10, 2002: Changed II (insertion iterator) from pass-by-reference to pass-by-value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
37
include/noncc/MSVC/1300/EmptyType.h
Executable file
37
include/noncc/MSVC/1300/EmptyType.h
Executable file
|
@ -0,0 +1,37 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef EMPTYTYPE_INC_
|
||||
#define EMPTYTYPE_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class EmptyType
|
||||
// Used as a class type that doesn't hold anything
|
||||
// Useful as a strawman class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EmptyType {};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EMPTYTYPE_INC_
|
143
include/noncc/MSVC/1300/Factory.h
Executable file
143
include/noncc/MSVC/1300/Factory.h
Executable file
|
@ -0,0 +1,143 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef FACTORY_INC_
|
||||
#define FACTORY_INC_
|
||||
|
||||
#include "LokiTypeInfo.h"
|
||||
#include "AssocVector.h"
|
||||
#include <exception>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultFactoryError
|
||||
// Manages the "Unknown Type" error in an object factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IdentifierType, class AbstractProduct>
|
||||
struct DefaultFactoryError
|
||||
{
|
||||
struct Exception : public std::exception
|
||||
{
|
||||
const char* what() const throw() { return "Unknown Type"; }
|
||||
};
|
||||
|
||||
static AbstractProduct* OnUnknownType(IdentifierType)
|
||||
{
|
||||
throw Exception();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Factory
|
||||
// Implements a generic object factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
typename IdentifierType,
|
||||
typename ProductCreator = AbstractProduct* (*)(),
|
||||
template<typename, class>
|
||||
class FactoryErrorPolicy = DefaultFactoryError
|
||||
>
|
||||
class Factory
|
||||
: public FactoryErrorPolicy<IdentifierType, AbstractProduct>
|
||||
{
|
||||
public:
|
||||
bool Register(const IdentifierType& id, ProductCreator creator)
|
||||
{
|
||||
return associations_.insert(
|
||||
IdToProductMap::value_type(id, creator)).second;
|
||||
}
|
||||
|
||||
bool Unregister(const IdentifierType& id)
|
||||
{
|
||||
return associations_.erase(id) == 1;
|
||||
}
|
||||
|
||||
AbstractProduct* CreateObject(const IdentifierType& id)
|
||||
{
|
||||
typename IdToProductMap::iterator i = associations_.find(id);
|
||||
if (i != associations_.end())
|
||||
{
|
||||
return (i->second)();
|
||||
}
|
||||
return OnUnknownType(id);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
|
||||
IdToProductMap associations_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CloneFactory
|
||||
// Implements a generic cloning factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
class ProductCreator =
|
||||
AbstractProduct* (*)(const AbstractProduct*),
|
||||
template<typename, class>
|
||||
class FactoryErrorPolicy = DefaultFactoryError
|
||||
>
|
||||
class CloneFactory
|
||||
: public FactoryErrorPolicy<TypeInfo, AbstractProduct>
|
||||
{
|
||||
public:
|
||||
bool Register(const TypeInfo& ti, ProductCreator creator)
|
||||
{
|
||||
return associations_.insert(
|
||||
IdToProductMap::value_type(ti, creator)).second;
|
||||
}
|
||||
|
||||
bool Unregister(const TypeInfo& id)
|
||||
{
|
||||
return associations_.erase(id) == 1;
|
||||
}
|
||||
|
||||
AbstractProduct* CreateObject(const AbstractProduct* model)
|
||||
{
|
||||
if (model == 0) return 0;
|
||||
|
||||
typename IdToProductMap::iterator i =
|
||||
associations_.find(typeid(*model));
|
||||
if (i != associations_.end())
|
||||
{
|
||||
return (i->second)(model);
|
||||
}
|
||||
return OnUnknownType(typeid(*model));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
|
||||
IdToProductMap associations_;
|
||||
};
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // FACTORY_INC_
|
1358
include/noncc/MSVC/1300/Functor.h
Executable file
1358
include/noncc/MSVC/1300/Functor.h
Executable file
File diff suppressed because it is too large
Load diff
423
include/noncc/MSVC/1300/HierarchyGenerators.h
Executable file
423
include/noncc/MSVC/1300/HierarchyGenerators.h
Executable file
|
@ -0,0 +1,423 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
|
||||
#pragma warning( push )
|
||||
|
||||
// 'class1' : base-class 'class2' is already a base-class of 'class3'
|
||||
#pragma warning( disable : 4584 )
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifndef HIERARCHYGENERATORS_INC_
|
||||
#define HIERARCHYGENERATORS_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeTraits.h"
|
||||
#include "EmptyType.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenScatterHierarchy
|
||||
// Generates a scattered hierarchy starting from a typelist and a template
|
||||
// Invocation (TList is a typelist, Model is a template of one arg):
|
||||
// GenScatterHierarchy<TList, Model>
|
||||
// The generated class inherits all classes generated by instantiating the
|
||||
// template 'Model' with the types contained in TList
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template <typename T, template <typename> class Unit>
|
||||
class GenScatterHierarchy;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
// for some reason VC7 needs the base definition altough not in use
|
||||
template <typename TListTag>
|
||||
struct GenScatterHierarchyHelper1
|
||||
{
|
||||
template <typename T, template <typename> class Unit>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename TListTag>
|
||||
struct GenScatterHierarchyHelper2
|
||||
{
|
||||
template <typename T, template <typename> class Unit>
|
||||
struct In
|
||||
{
|
||||
typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper1<TL::Typelist_tag>
|
||||
{
|
||||
template <class TList, template <typename> class Unit>
|
||||
struct In
|
||||
{
|
||||
typedef GenScatterHierarchy<typename TList::Head, Unit> Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper2<TL::Typelist_tag>
|
||||
{
|
||||
template <class TList, template <typename> class Unit>
|
||||
struct In
|
||||
{
|
||||
typedef GenScatterHierarchy<typename TList::Tail, Unit> Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper1<TL::NoneList_tag>
|
||||
{
|
||||
template <typename AtomicType, template <typename> class Unit>
|
||||
struct In { typedef Unit<AtomicType> Result; };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper2<TL::NoneList_tag>
|
||||
{
|
||||
template <typename AtomicType, template <typename> class Unit>
|
||||
struct In { struct Result {}; };
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper1<TL::NullType_tag>
|
||||
{
|
||||
template <class TList, template <typename> class Unit>
|
||||
struct In { struct Result {}; };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenScatterHierarchyHelper2<TL::NullType_tag>
|
||||
{
|
||||
template <class TList, template <typename> class Unit>
|
||||
struct In { struct Result {}; };
|
||||
};
|
||||
|
||||
} // namespace Private
|
||||
|
||||
template <typename T, template <typename> class Unit>
|
||||
class GenScatterHierarchy
|
||||
: public Private::GenScatterHierarchyHelper1
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, Unit>::Result
|
||||
|
||||
, public Private::GenScatterHierarchyHelper2
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, Unit>::Result
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename Private::GenScatterHierarchyHelper1
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, Unit>::Result LeftBase;
|
||||
|
||||
typedef typename Private::GenScatterHierarchyHelper2
|
||||
<
|
||||
typename TL::is_Typelist<T>::type_tag
|
||||
>
|
||||
::template In<T, Unit>::Result RightBase;
|
||||
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
TL::is_Typelist<T>::value, T, void
|
||||
>
|
||||
::Result TList;
|
||||
|
||||
template <typename T> struct Rebind
|
||||
{
|
||||
typedef Unit<T> Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template Field
|
||||
// Accesses a field in an object of a type generated with GenScatterHierarchy
|
||||
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
|
||||
// T is a type in the typelist used to generate H):
|
||||
// Field<T>(obj)
|
||||
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class H>
|
||||
typename H::template Rebind<T>::Result &
|
||||
Field(H& obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class T, class H>
|
||||
typename H::template Rebind<T>::Result const &
|
||||
Field(H const & obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template TupleUnit
|
||||
// The building block of tuples
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct TupleUnit
|
||||
{
|
||||
T value_;
|
||||
operator T&() { return value_; }
|
||||
operator const T&() const { return value_; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Tuple
|
||||
// Implements a tuple class that holds a number of values and provides field
|
||||
// access to them via the Field function (below)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList>
|
||||
struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// helper class template FieldHelper
|
||||
// See Field below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <unsigned int i>
|
||||
struct FieldHelper
|
||||
{
|
||||
template<class H>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
|
||||
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
||||
|
||||
enum { isConst = TypeTraits<H>::isConst };
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const typename H::RightBase,
|
||||
typename H::RightBase
|
||||
>
|
||||
::Result RightBase;
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
IsSameType<UnitType, TupleUnit<ElementType> >::value,
|
||||
ElementType,
|
||||
UnitType
|
||||
>
|
||||
::Result UnqualifiedResultType;
|
||||
|
||||
public:
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const UnqualifiedResultType,
|
||||
UnqualifiedResultType
|
||||
>
|
||||
::Result ResultType;
|
||||
|
||||
static ResultType& Do(H& obj)
|
||||
{
|
||||
RightBase& rightBase = obj;
|
||||
return FieldHelper<i - 1>::template In<RightBase>::Do(rightBase);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct FieldHelper<0>
|
||||
{
|
||||
template<class H>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename H::TList::Head ElementType;
|
||||
typedef typename H::template Rebind<ElementType>::Result UnitType;
|
||||
|
||||
enum { isConst = TypeTraits<H>::isConst };
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const typename H::LeftBase,
|
||||
typename H::LeftBase
|
||||
>
|
||||
::Result LeftBase;
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
IsSameType<UnitType, TupleUnit<ElementType> >::value,
|
||||
ElementType,
|
||||
UnitType
|
||||
>
|
||||
::Result UnqualifiedResultType;
|
||||
|
||||
public:
|
||||
typedef typename Select
|
||||
<
|
||||
isConst,
|
||||
const UnqualifiedResultType,
|
||||
UnqualifiedResultType
|
||||
>
|
||||
::Result ResultType;
|
||||
|
||||
static ResultType& Do(H& obj)
|
||||
{
|
||||
LeftBase& leftBase = obj;
|
||||
return leftBase;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template Field
|
||||
// Accesses a field in an object of a type generated with GenScatterHierarchy
|
||||
// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
|
||||
// i is the index of a type in the typelist used to generate H):
|
||||
// Field<i>(obj)
|
||||
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
||||
// and T is the i-th type in the typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <unsigned int i, class H>
|
||||
typename FieldHelper<i>::template In<H>::ResultType&
|
||||
Field(H& obj)
|
||||
{
|
||||
return FieldHelper<i>::template In<H>::Do(obj);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenLinearHierarchy
|
||||
// Generates a linear hierarchy starting from a typelist and a template
|
||||
// Invocation (TList is a typelist, Model is a template of two args):
|
||||
// GenLinearHierarchy<TList, Model, Root>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
template <class AtomicType, class UnitBase> class Unit,
|
||||
class Root = EmptyType
|
||||
>
|
||||
class GenLinearHierarchy;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
|
||||
template <typename TListTag>
|
||||
struct GenLinearHierarchyHelper
|
||||
{
|
||||
template<class TList, template <class, class> class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenLinearHierarchyHelper<TL::Typelist_tag>
|
||||
{
|
||||
template<class TList, template <class, class> class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
public:
|
||||
typedef Unit< Head, GenLinearHierarchy<Tail, Unit, Root> > Result;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GenLinearHierarchyHelper<TL::NullType_tag>
|
||||
{
|
||||
template<class TList, template <class, class> class Unit, class Root>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TList::Head Head;
|
||||
|
||||
public:
|
||||
typedef Unit<Head, Root> Result;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Private
|
||||
|
||||
template
|
||||
<
|
||||
class TList,
|
||||
template <class AtomicType, class UnitBase> class Unit,
|
||||
class Root
|
||||
>
|
||||
class GenLinearHierarchy
|
||||
: public Private::GenLinearHierarchyHelper
|
||||
<
|
||||
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
||||
>
|
||||
::template In<TList, Unit, Root>::Result
|
||||
{
|
||||
ASSERT_TYPELIST(TList); // TList must not be NullType
|
||||
|
||||
public:
|
||||
typedef typename Private::GenLinearHierarchyHelper
|
||||
<
|
||||
typename TL::is_Typelist<typename TList::Tail>::type_tag
|
||||
>
|
||||
::template In<TList, Unit, Root>::Result LinBase;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // HIERARCHYGENERATORS_INC_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif // _MSC_VER
|
||||
|
107
include/noncc/MSVC/1300/LokiTypeInfo.h
Executable file
107
include/noncc/MSVC/1300/LokiTypeInfo.h
Executable file
|
@ -0,0 +1,107 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef LOKITYPEINFO_INC_
|
||||
#define LOKITYPEINFO_INC_
|
||||
|
||||
#include <typeinfo>
|
||||
#include <cassert>
|
||||
#include "Typelist.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class TypeInfo
|
||||
// Purpose: offer a first-class, comparable wrapper over std::type_info
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TypeInfo
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
TypeInfo(); // needed for containers
|
||||
TypeInfo(const std::type_info&); // non-explicit
|
||||
|
||||
// Access for the wrapped std::type_info
|
||||
const std::type_info& Get() const;
|
||||
// Compatibility functions
|
||||
bool before(const TypeInfo& rhs) const;
|
||||
const char* name() const;
|
||||
|
||||
private:
|
||||
const std::type_info* pInfo_;
|
||||
};
|
||||
|
||||
// Implementation
|
||||
|
||||
inline TypeInfo::TypeInfo()
|
||||
{
|
||||
class Nil {};
|
||||
pInfo_ = &typeid(Nil);
|
||||
assert(pInfo_);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(const std::type_info& ti)
|
||||
: pInfo_(&ti)
|
||||
{ assert(pInfo_); }
|
||||
|
||||
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return pInfo_->before(*rhs.pInfo_) != 0;
|
||||
}
|
||||
|
||||
inline const std::type_info& TypeInfo::Get() const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return *pInfo_;
|
||||
}
|
||||
|
||||
inline const char* TypeInfo::name() const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return pInfo_->name();
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
|
||||
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return (lhs.Get() == rhs.Get()) != 0; }
|
||||
|
||||
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return lhs.before(rhs); }
|
||||
|
||||
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs == rhs); }
|
||||
|
||||
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return rhs < lhs; }
|
||||
|
||||
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs > rhs); }
|
||||
|
||||
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return !(lhs < rhs); }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // LOKITYPEINFO_INC_
|
112
include/noncc/MSVC/1300/MinMax.h
Executable file
112
include/noncc/MSVC/1300/MinMax.h
Executable 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
include/noncc/MSVC/1300/MultiMethods.h
Executable file
418
include/noncc/MSVC/1300/MultiMethods.h
Executable 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
|
44
include/noncc/MSVC/1300/NullType.h
Executable file
44
include/noncc/MSVC/1300/NullType.h
Executable file
|
@ -0,0 +1,44 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef NULLTYPE_INC_
|
||||
#define NULLTYPE_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class NullType
|
||||
// Used as a placeholder for "no type here"
|
||||
// Useful as an end marker in typelists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NullType
|
||||
{
|
||||
public:
|
||||
struct Head { private: Head(); };
|
||||
struct Tail { private: Tail(); };
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // NULLTYPE_INC_
|
||||
|
48
include/noncc/MSVC/1300/Singleton.cpp
Executable file
48
include/noncc/MSVC/1300/Singleton.cpp
Executable file
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
using namespace Loki::Private;
|
||||
|
||||
Loki::Private::TrackerArray Loki::Private::pTrackerArray = 0;
|
||||
unsigned int Loki::Private::elements = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function AtExitFn
|
||||
// Ensures proper destruction of objects with longevity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void C_CALLING_CONVENTION_QUALIFIER Loki::Private::AtExitFn()
|
||||
{
|
||||
assert(elements > 0 && pTrackerArray != 0);
|
||||
// Pick the element at the top of the stack
|
||||
LifetimeTracker* pTop = pTrackerArray[elements - 1];
|
||||
// Remove that object off the stack
|
||||
// Don't check errors - realloc with less memory
|
||||
// can't fail
|
||||
pTrackerArray = static_cast<TrackerArray>(std::realloc(
|
||||
pTrackerArray, sizeof(*pTrackerArray) * --elements));
|
||||
// Destroy the element
|
||||
delete pTop;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
442
include/noncc/MSVC/1300/Singleton.h
Executable file
442
include/noncc/MSVC/1300/Singleton.h
Executable file
|
@ -0,0 +1,442 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef SINGLETON_INC_
|
||||
#define SINGLETON_INC_
|
||||
|
||||
#include "Threads.h"
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define C_CALLING_CONVENTION_QUALIFIER __cdecl
|
||||
#else
|
||||
#define C_CALLING_CONVENTION_QUALIFIER
|
||||
#endif
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
typedef void (C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)();
|
||||
|
||||
namespace Private
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class LifetimeTracker
|
||||
// Helper class for SetLongevity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LifetimeTracker
|
||||
{
|
||||
public:
|
||||
LifetimeTracker(unsigned int x) : longevity_(x)
|
||||
{}
|
||||
|
||||
virtual ~LifetimeTracker() = 0;
|
||||
|
||||
static bool Compare(const LifetimeTracker* lhs,
|
||||
const LifetimeTracker* rhs)
|
||||
{
|
||||
return lhs->longevity_ > rhs->longevity_;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int longevity_;
|
||||
};
|
||||
|
||||
// Definition required
|
||||
inline LifetimeTracker::~LifetimeTracker() {}
|
||||
|
||||
// Helper data
|
||||
typedef LifetimeTracker** TrackerArray;
|
||||
extern TrackerArray pTrackerArray;
|
||||
extern unsigned int elements;
|
||||
|
||||
// Helper destroyer function
|
||||
template <typename T>
|
||||
struct Deleter
|
||||
{
|
||||
static void Delete(T* pObj)
|
||||
{ delete pObj; }
|
||||
};
|
||||
|
||||
// Concrete lifetime tracker for objects of type T
|
||||
template <typename T, typename Destroyer>
|
||||
class ConcreteLifetimeTracker : public LifetimeTracker
|
||||
{
|
||||
public:
|
||||
ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
|
||||
: LifetimeTracker(longevity)
|
||||
, pTracked_(p)
|
||||
, destroyer_(d)
|
||||
{}
|
||||
|
||||
~ConcreteLifetimeTracker()
|
||||
{ destroyer_(pTracked_); }
|
||||
|
||||
private:
|
||||
T* pTracked_;
|
||||
Destroyer destroyer_;
|
||||
};
|
||||
|
||||
void C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below
|
||||
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template SetLongevity
|
||||
// Assigns an object a longevity; ensures ordered destructions of objects
|
||||
// registered thusly during the exit sequence of the application
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename Destroyer>
|
||||
void SetLongevity(T* pDynObject, unsigned int longevity,
|
||||
Destroyer d = Private::Deleter<T>::Delete)
|
||||
{
|
||||
using namespace Private;
|
||||
|
||||
TrackerArray pNewArray = static_cast<TrackerArray>(
|
||||
std::realloc(pTrackerArray, sizeof(*pTrackerArray) * (elements + 1)));
|
||||
if (!pNewArray) throw std::bad_alloc();
|
||||
|
||||
// Delayed assignment for exception safety
|
||||
pTrackerArray = pNewArray;
|
||||
|
||||
LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
|
||||
pDynObject, longevity, d);
|
||||
|
||||
// Insert a pointer to the object into the queue
|
||||
TrackerArray pos = std::upper_bound(
|
||||
pTrackerArray,
|
||||
pTrackerArray + elements,
|
||||
p,
|
||||
LifetimeTracker::Compare);
|
||||
std::copy_backward(
|
||||
pos,
|
||||
pTrackerArray + elements,
|
||||
pTrackerArray + elements + 1);
|
||||
*pos = p;
|
||||
++elements;
|
||||
|
||||
// Register a call to AtExitFn
|
||||
std::atexit(Private::AtExitFn);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CreateUsingNew
|
||||
// Implementation of the CreationPolicy used by SingletonHolder
|
||||
// Creates objects using a straight call to the new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> struct CreateUsingNew
|
||||
{
|
||||
static T* Create()
|
||||
{ return new T; }
|
||||
|
||||
static void Destroy(T* p)
|
||||
{ delete p; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CreateUsingNew
|
||||
// Implementation of the CreationPolicy used by SingletonHolder
|
||||
// Creates objects using a call to std::malloc, followed by a call to the
|
||||
// placement new operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> struct CreateUsingMalloc
|
||||
{
|
||||
static T* Create()
|
||||
{
|
||||
void* p = std::malloc(sizeof(T));
|
||||
if (!p) return 0;
|
||||
return new(p) T;
|
||||
}
|
||||
|
||||
static void Destroy(T* p)
|
||||
{
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template CreateStatic
|
||||
// Implementation of the CreationPolicy used by SingletonHolder
|
||||
// Creates an object in static memory
|
||||
// Implementation is slightly nonportable because it uses the MaxAlign trick
|
||||
// (an union of all types to ensure proper memory alignment). This trick is
|
||||
// nonportable in theory but highly portable in practice.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> struct CreateStatic
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
// alignment of a member was sensitive to packing
|
||||
#pragma warning( disable : 4121 )
|
||||
#endif // _MSC_VER
|
||||
union MaxAlign
|
||||
{
|
||||
char t_[sizeof(T)];
|
||||
short int shortInt_;
|
||||
int int_;
|
||||
long int longInt_;
|
||||
float float_;
|
||||
double double_;
|
||||
long double longDouble_;
|
||||
struct Test;
|
||||
int Test::* pMember_;
|
||||
int (Test::*pMemberFn_)(int);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif // _MSC_VER
|
||||
|
||||
static T* Create()
|
||||
{
|
||||
static MaxAlign staticMemory_;
|
||||
return new(&staticMemory_) T;
|
||||
}
|
||||
|
||||
static void Destroy(T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template DefaultLifetime
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction as per C++ rules
|
||||
// Forwards to std::atexit
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct DefaultLifetime
|
||||
{
|
||||
static void ScheduleDestruction(T*, atexit_pfn_t pFun)
|
||||
{ std::atexit(pFun); }
|
||||
|
||||
static void OnDeadReference()
|
||||
{ throw std::logic_error("Dead Reference Detected"); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template PhoenixSingleton
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction as per C++ rules, and it allows object
|
||||
// recreation by not throwing an exception from OnDeadReference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class PhoenixSingleton
|
||||
{
|
||||
public:
|
||||
static void ScheduleDestruction(T*, atexit_pfn_t pFun)
|
||||
{
|
||||
#ifndef ATEXIT_FIXED
|
||||
if (!destroyedOnce_)
|
||||
#endif
|
||||
std::atexit(pFun);
|
||||
}
|
||||
|
||||
static void OnDeadReference()
|
||||
{
|
||||
#ifndef ATEXIT_FIXED
|
||||
destroyedOnce_ = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifndef ATEXIT_FIXED
|
||||
static bool destroyedOnce_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef ATEXIT_FIXED
|
||||
template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Adapter
|
||||
// Helper for SingletonWithLongevity below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template <class T>
|
||||
struct Adapter
|
||||
{
|
||||
void operator()(T*) { return pFun_(); }
|
||||
atexit_pfn_t pFun_;
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonWithLongevity
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Schedules an object's destruction in order of their longevities
|
||||
// Assumes a visible function GetLongevity(T*) that returns the longevity of the
|
||||
// object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class SingletonWithLongevity
|
||||
{
|
||||
public:
|
||||
static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
|
||||
{
|
||||
Private::Adapter<T> adapter = { pFun };
|
||||
SetLongevity(pObj, GetLongevity(pObj), adapter);
|
||||
}
|
||||
|
||||
static void OnDeadReference()
|
||||
{ throw std::logic_error("Dead Reference Detected"); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template NoDestroy
|
||||
// Implementation of the LifetimePolicy used by SingletonHolder
|
||||
// Never destroys the object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct NoDestroy
|
||||
{
|
||||
static void ScheduleDestruction(T*, atexit_pfn_t)
|
||||
{}
|
||||
|
||||
static void OnDeadReference()
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingletonHolder
|
||||
// Provides Singleton amenities for a type T
|
||||
// To protect that type from spurious instantiations, you have to protect it
|
||||
// yourself.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
class ClientType,
|
||||
class ThreadingModelType,
|
||||
class PtrInstanceType
|
||||
>
|
||||
class SingletonHolderStaticData
|
||||
{
|
||||
friend ClientType; // illegal (11.4/2) but works with VC
|
||||
static PtrInstanceType s_pInstance;
|
||||
static bool s_destroyed;
|
||||
};
|
||||
|
||||
template<class C, class M, class P>
|
||||
P SingletonHolderStaticData<C, M, P>::s_pInstance;
|
||||
|
||||
template<class C, class M, class P>
|
||||
bool SingletonHolderStaticData<C, M, P>::s_destroyed;
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
template <class> class CreationPolicy = CreateUsingNew,
|
||||
template <class> class LifetimePolicy = DefaultLifetime,
|
||||
template <class> class ThreadingModel = SingleThreaded
|
||||
>
|
||||
class SingletonHolder
|
||||
{
|
||||
typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
|
||||
|
||||
typedef SingletonHolderStaticData
|
||||
<
|
||||
SingletonHolder,
|
||||
ThreadingModel<T>,
|
||||
PtrInstanceType
|
||||
>
|
||||
MySingletonHolderStaticData;
|
||||
|
||||
public:
|
||||
static T& Instance()
|
||||
{
|
||||
if (!pInstance_())
|
||||
{
|
||||
MakeInstance();
|
||||
}
|
||||
return *pInstance_();
|
||||
}
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
static void MakeInstance()
|
||||
{
|
||||
typename ThreadingModel<SingletonHolder>::Lock guard;
|
||||
(void)guard;
|
||||
|
||||
if (!pInstance_())
|
||||
{
|
||||
if (destroyed_())
|
||||
{
|
||||
LifetimePolicy<T>::OnDeadReference();
|
||||
destroyed_() = false;
|
||||
}
|
||||
|
||||
pInstance_() = CreationPolicy<T>::Create();
|
||||
|
||||
LifetimePolicy<T>::ScheduleDestruction
|
||||
(
|
||||
pInstance_(),
|
||||
&DestroySingleton
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void C_CALLING_CONVENTION_QUALIFIER DestroySingleton()
|
||||
{
|
||||
assert(!destroyed_());
|
||||
CreationPolicy<T>::Destroy(pInstance_());
|
||||
pInstance_() = 0;
|
||||
destroyed_() = true;
|
||||
}
|
||||
|
||||
// Protection
|
||||
SingletonHolder();
|
||||
|
||||
// Data
|
||||
static PtrInstanceType &pInstance_()
|
||||
{
|
||||
return MySingletonHolderStaticData::s_pInstance;
|
||||
}
|
||||
|
||||
static bool &destroyed_()
|
||||
{
|
||||
return MySingletonHolderStaticData::s_destroyed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SINGLETON_INC_
|
612
include/noncc/MSVC/1300/SmallObj.cpp
Executable file
612
include/noncc/MSVC/1300/SmallObj.cpp
Executable file
|
@ -0,0 +1,612 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Header$
|
||||
|
||||
|
||||
#include "SmallObj.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
|
||||
using namespace Loki;
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class FixedAllocator
|
||||
// Offers services for allocating fixed-sized objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FixedAllocator
|
||||
{
|
||||
private:
|
||||
struct Chunk
|
||||
{
|
||||
bool Init( std::size_t blockSize, unsigned char blocks );
|
||||
void* Allocate(std::size_t blockSize);
|
||||
void Deallocate(void* p, std::size_t blockSize);
|
||||
void Reset(std::size_t blockSize, unsigned char blocks);
|
||||
void Release();
|
||||
inline bool HasBlock( unsigned char * p, std::size_t chunkLength ) const
|
||||
{ return ( pData_ <= p ) && ( p < pData_ + chunkLength ); }
|
||||
|
||||
inline bool HasAvailable( unsigned char numBlocks ) const
|
||||
{ return ( blocksAvailable_ == numBlocks ); }
|
||||
|
||||
inline bool IsFilled( void ) const
|
||||
{ return ( 0 == blocksAvailable_ ); }
|
||||
|
||||
unsigned char* pData_;
|
||||
unsigned char
|
||||
firstAvailableBlock_,
|
||||
blocksAvailable_;
|
||||
};
|
||||
|
||||
// Internal functions
|
||||
void DoDeallocate(void* p);
|
||||
|
||||
bool MakeNewChunk( void );
|
||||
|
||||
Chunk * VicinityFind( void * p );
|
||||
|
||||
/// Not implemented.
|
||||
FixedAllocator(const FixedAllocator&);
|
||||
/// Not implemented.
|
||||
FixedAllocator& operator=(const FixedAllocator&);
|
||||
|
||||
// Data
|
||||
std::size_t blockSize_;
|
||||
unsigned char numBlocks_;
|
||||
typedef std::vector<Chunk> Chunks;
|
||||
typedef Chunks::iterator ChunkIter;
|
||||
typedef Chunks::const_iterator ChunkCIter;
|
||||
Chunks chunks_;
|
||||
Chunk* allocChunk_;
|
||||
Chunk* deallocChunk_;
|
||||
Chunk * emptyChunk_;
|
||||
|
||||
public:
|
||||
// Create a FixedAllocator able to manage blocks of 'blockSize' size
|
||||
FixedAllocator();
|
||||
~FixedAllocator();
|
||||
|
||||
void Initialize( std::size_t blockSize, std::size_t pageSize );
|
||||
|
||||
// Allocate a memory block
|
||||
void * Allocate( void );
|
||||
|
||||
// Deallocate a memory block previously allocated with Allocate()
|
||||
// (if that's not the case, the behavior is undefined)
|
||||
bool Deallocate( void * p, bool doChecks );
|
||||
// Returns the block size with which the FixedAllocator was initialized
|
||||
inline std::size_t BlockSize() const
|
||||
{ return blockSize_; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Init
|
||||
// Initializes a chunk object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FixedAllocator::Chunk::Init( std::size_t blockSize, unsigned char blocks )
|
||||
{
|
||||
assert(blockSize > 0);
|
||||
assert(blocks > 0);
|
||||
// Overflow check
|
||||
const std::size_t allocSize = blockSize * blocks;
|
||||
assert( allocSize / blockSize == blocks);
|
||||
|
||||
#ifdef USE_NEW_TO_ALLOCATE
|
||||
// If this new operator fails, it will throw, and the exception will get
|
||||
// caught one layer up.
|
||||
pData_ = new unsigned char[ allocSize ];
|
||||
#else
|
||||
// malloc can't throw, so its only way to indicate an error is to return
|
||||
// a NULL pointer, so we have to check for that.
|
||||
pData_ = static_cast< unsigned char * >( ::malloc( allocSize ) );
|
||||
if ( NULL == pData_ ) return false;
|
||||
#endif
|
||||
|
||||
Reset( blockSize, blocks );
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Reset
|
||||
// Clears an already allocated chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Reset(std::size_t blockSize, unsigned char blocks)
|
||||
{
|
||||
assert(blockSize > 0);
|
||||
assert(blocks > 0);
|
||||
// Overflow check
|
||||
assert((blockSize * blocks) / blockSize == blocks);
|
||||
|
||||
firstAvailableBlock_ = 0;
|
||||
blocksAvailable_ = blocks;
|
||||
|
||||
unsigned char i = 0;
|
||||
unsigned char* p = pData_;
|
||||
for (; i != blocks; p += blockSize)
|
||||
{
|
||||
*p = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Release
|
||||
// Releases the data managed by a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Release()
|
||||
{
|
||||
assert( NULL != pData_ );
|
||||
#ifdef USE_NEW_TO_ALLOCATE
|
||||
delete [] pData_;
|
||||
#else
|
||||
::free( static_cast< void * >( pData_ ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Allocate
|
||||
// Allocates a block from a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* FixedAllocator::Chunk::Allocate(std::size_t blockSize)
|
||||
{
|
||||
if ( IsFilled() ) return NULL;
|
||||
|
||||
assert((firstAvailableBlock_ * blockSize) / blockSize ==
|
||||
firstAvailableBlock_);
|
||||
unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize);
|
||||
firstAvailableBlock_ = *pResult;
|
||||
--blocksAvailable_;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Chunk::Deallocate
|
||||
// Dellocates a block from a chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Chunk::Deallocate(void* p, std::size_t blockSize)
|
||||
{
|
||||
assert(p >= pData_);
|
||||
|
||||
unsigned char* toRelease = static_cast<unsigned char*>(p);
|
||||
// Alignment check
|
||||
assert((toRelease - pData_) % blockSize == 0);
|
||||
|
||||
*toRelease = firstAvailableBlock_;
|
||||
firstAvailableBlock_ = static_cast<unsigned char>(
|
||||
(toRelease - pData_) / blockSize);
|
||||
// Truncation check
|
||||
assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);
|
||||
|
||||
++blocksAvailable_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::FixedAllocator
|
||||
// Creates a FixedAllocator object of a fixed block size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::FixedAllocator()
|
||||
: blockSize_( 0 )
|
||||
, allocChunk_( NULL )
|
||||
, deallocChunk_( NULL )
|
||||
, emptyChunk_( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::~FixedAllocator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::~FixedAllocator()
|
||||
{
|
||||
for ( ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i )
|
||||
i->Release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Initialize
|
||||
// Initializes the operational constraints for the FixedAllocator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize )
|
||||
{
|
||||
assert( blockSize > 0 );
|
||||
assert( pageSize >= blockSize );
|
||||
blockSize_ = blockSize;
|
||||
|
||||
std::size_t numBlocks = pageSize / blockSize;
|
||||
if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX;
|
||||
else if ( numBlocks < 8 ) numBlocks = 8;
|
||||
|
||||
numBlocks_ = static_cast<unsigned char>(numBlocks);
|
||||
assert(numBlocks_ == numBlocks);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::MakeNewChunk
|
||||
// Allocates a new Chunk for a FixedAllocator.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FixedAllocator::MakeNewChunk( void )
|
||||
{
|
||||
bool allocated = false;
|
||||
try
|
||||
{
|
||||
// Calling chunks_.reserve *before* creating and initializing the new
|
||||
// Chunk means that nothing is leaked by this function in case an
|
||||
// exception is thrown from reserve.
|
||||
chunks_.reserve( chunks_.size() + 1 );
|
||||
Chunk newChunk;
|
||||
allocated = newChunk.Init( blockSize_, numBlocks_ );
|
||||
if ( allocated )
|
||||
chunks_.push_back( newChunk );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
allocated = false;
|
||||
}
|
||||
if ( !allocated ) return false;
|
||||
|
||||
allocChunk_ = &chunks_.back();
|
||||
deallocChunk_ = &chunks_.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Allocate
|
||||
// Allocates a block of fixed size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void * FixedAllocator::Allocate( void )
|
||||
{
|
||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||
|
||||
if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() )
|
||||
{
|
||||
if ( NULL != emptyChunk_ )
|
||||
{
|
||||
allocChunk_ = emptyChunk_;
|
||||
emptyChunk_ = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ChunkIter i( chunks_.begin() ); ; ++i )
|
||||
{
|
||||
if ( chunks_.end() == i )
|
||||
{
|
||||
if ( !MakeNewChunk() )
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
if ( !i->IsFilled() )
|
||||
{
|
||||
allocChunk_ = &*i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( allocChunk_ == emptyChunk_)
|
||||
// detach emptyChunk_ from allocChunk_, because after
|
||||
// calling allocChunk_->Allocate(blockSize_); the chunk
|
||||
// isn't any more empty
|
||||
emptyChunk_ = NULL;
|
||||
|
||||
assert( allocChunk_ != NULL );
|
||||
assert( !allocChunk_->IsFilled() );
|
||||
void *place = allocChunk_->Allocate(blockSize_);
|
||||
|
||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||
|
||||
return place;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::Deallocate
|
||||
// Deallocates a block previously allocated with Allocate
|
||||
// (undefined behavior if called with the wrong pointer)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FixedAllocator::Deallocate( void * p, bool doChecks )
|
||||
{
|
||||
if ( doChecks )
|
||||
{
|
||||
assert(!chunks_.empty());
|
||||
assert(&chunks_.front() <= deallocChunk_);
|
||||
assert(&chunks_.back() >= deallocChunk_);
|
||||
assert( &chunks_.front() <= allocChunk_ );
|
||||
assert( &chunks_.back() >= allocChunk_ );
|
||||
}
|
||||
|
||||
Chunk * foundChunk = VicinityFind( p );
|
||||
if ( doChecks )
|
||||
{
|
||||
assert( NULL != foundChunk );
|
||||
}
|
||||
else if ( NULL == foundChunk )
|
||||
return false;
|
||||
|
||||
deallocChunk_ = foundChunk;
|
||||
DoDeallocate(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::VicinityFind (internal)
|
||||
// Finds the chunk corresponding to a pointer, using an efficient search
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FixedAllocator::Chunk * FixedAllocator::VicinityFind( void * p )
|
||||
{
|
||||
if ( chunks_.empty() ) return NULL;
|
||||
assert(deallocChunk_);
|
||||
|
||||
unsigned char * pc = static_cast< unsigned char * >( p );
|
||||
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||
|
||||
Chunk* lo = deallocChunk_;
|
||||
Chunk* hi = deallocChunk_ + 1;
|
||||
Chunk* loBound = &chunks_.front();
|
||||
Chunk* hiBound = &chunks_.back() + 1;
|
||||
|
||||
// Special case: deallocChunk_ is the last in the array
|
||||
if (hi == hiBound) hi = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (lo)
|
||||
{
|
||||
if ( lo->HasBlock( pc, chunkLength ) ) return lo;
|
||||
if ( lo == loBound )
|
||||
{
|
||||
lo = NULL;
|
||||
if ( NULL == hi ) break;
|
||||
}
|
||||
else --lo;
|
||||
}
|
||||
|
||||
if (hi)
|
||||
{
|
||||
if ( hi->HasBlock( pc, chunkLength ) ) return hi;
|
||||
if ( ++hi == hiBound )
|
||||
{
|
||||
hi = NULL;
|
||||
if ( NULL == lo ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FixedAllocator::DoDeallocate (internal)
|
||||
// Performs deallocation. Assumes deallocChunk_ points to the correct chunk
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FixedAllocator::DoDeallocate(void* p)
|
||||
{
|
||||
assert( deallocChunk_->HasBlock( static_cast< unsigned char * >( p ),
|
||||
numBlocks_ * blockSize_ ) );
|
||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||
|
||||
// call into the chunk, will adjust the inner list but won't release memory
|
||||
deallocChunk_->Deallocate(p, blockSize_);
|
||||
|
||||
if ( deallocChunk_->HasAvailable( numBlocks_ ) )
|
||||
{
|
||||
assert( emptyChunk_ != deallocChunk_ );
|
||||
// deallocChunk_ is empty, but a Chunk is only released if there are 2
|
||||
// empty chunks. Since emptyChunk_ may only point to a previously
|
||||
// cleared Chunk, if it points to something else besides deallocChunk_,
|
||||
// then FixedAllocator currently has 2 empty Chunks.
|
||||
if ( NULL != emptyChunk_ )
|
||||
{
|
||||
// If last Chunk is empty, just change what deallocChunk_
|
||||
// points to, and release the last. Otherwise, swap an empty
|
||||
// Chunk with the last, and then release it.
|
||||
Chunk * lastChunk = &chunks_.back();
|
||||
if ( lastChunk == deallocChunk_ )
|
||||
deallocChunk_ = emptyChunk_;
|
||||
else if ( lastChunk != emptyChunk_ )
|
||||
std::swap( *emptyChunk_, *lastChunk );
|
||||
assert( lastChunk->HasAvailable( numBlocks_ ) );
|
||||
lastChunk->Release();
|
||||
chunks_.pop_back();
|
||||
allocChunk_ = deallocChunk_;
|
||||
}
|
||||
emptyChunk_ = deallocChunk_;
|
||||
}
|
||||
|
||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GetOffset
|
||||
// Calculates index into array where a FixedAllocator of numBytes is located.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment )
|
||||
{
|
||||
const std::size_t alignExtra = alignment-1;
|
||||
return ( numBytes + alignExtra ) / alignment;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DefaultAllocator
|
||||
// Call to default allocator when SmallObjAllocator decides not to handle request.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void * DefaultAllocator( std::size_t numBytes, bool doThrow )
|
||||
{
|
||||
#ifdef USE_NEW_TO_ALLOCATE
|
||||
return doThrow ? ::operator new( numBytes ) :
|
||||
::operator new( numBytes, std::nothrow_t() );
|
||||
#else
|
||||
void * p = ::malloc( numBytes );
|
||||
if ( doThrow && ( NULL == p ) )
|
||||
throw std::bad_alloc();
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DefaultDeallocator
|
||||
// Call to default deallocator when SmallObjAllocator decides not to handle request.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DefaultDeallocator( void * p )
|
||||
{
|
||||
#ifdef USE_NEW_TO_ALLOCATE
|
||||
::operator delete( p );
|
||||
#else
|
||||
::free( p );
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::SmallObjAllocator
|
||||
// Creates a SmallObjAllocator, and all the FixedAllocators within it. Each
|
||||
// FixedAllocator is then initialized to use the correct Chunk size.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SmallObjAllocator::SmallObjAllocator( std::size_t pageSize,
|
||||
std::size_t maxObjectSize, std::size_t objectAlignSize ) :
|
||||
pool_( NULL ),
|
||||
maxSmallObjectSize_( maxObjectSize ),
|
||||
objectAlignSize_( objectAlignSize )
|
||||
{
|
||||
assert( 0 != objectAlignSize );
|
||||
const std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize );
|
||||
pool_ = new FixedAllocator[ allocCount ];
|
||||
for ( std::size_t i = 0; i < allocCount; ++i )
|
||||
pool_[ i ].Initialize( ( i+1 ) * objectAlignSize, pageSize );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::~SmallObjAllocator
|
||||
// Deletes all memory consumed by SmallObjAllocator.
|
||||
// This deletes all the FixedAllocator's in the pool.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SmallObjAllocator::~SmallObjAllocator( void )
|
||||
{
|
||||
delete [] pool_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::Allocate
|
||||
// Handles request to allocate numBytes for 1 object.
|
||||
// This acts in constant-time - except for the calls to DefaultAllocator
|
||||
// and sometimes FixedAllocator::Allocate. It throws bad_alloc only if the
|
||||
// doThrow parameter is true and can't allocate another block. Otherwise, it
|
||||
// provides the no-throw exception safety level.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
|
||||
{
|
||||
if ( numBytes > GetMaxObjectSize() )
|
||||
return DefaultAllocator( numBytes, doThrow );
|
||||
|
||||
assert( NULL != pool_ );
|
||||
if ( 0 == numBytes ) numBytes = 1;
|
||||
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
||||
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||
assert( index < allocCount );
|
||||
|
||||
FixedAllocator & allocator = pool_[ index ];
|
||||
assert( allocator.BlockSize() >= numBytes );
|
||||
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
||||
void * place = allocator.Allocate();
|
||||
if ( ( NULL == place ) && doThrow )
|
||||
{
|
||||
#if _MSC_VER
|
||||
throw std::bad_alloc( "could not allocate small object" );
|
||||
#else
|
||||
// GCC did not like a literal string passed to std::bad_alloc.
|
||||
// so just throw the default-constructed exception.
|
||||
throw std::bad_alloc();
|
||||
#endif
|
||||
}
|
||||
return place;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::Deallocate
|
||||
// Handles request to deallocate numBytes for 1 object.
|
||||
// This will act in constant-time - except for the calls to DefaultDeallocator
|
||||
// and sometimes FixedAllocator::Deallocate. It will never throw.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
|
||||
{
|
||||
if ( NULL == p ) return;
|
||||
if ( numBytes > GetMaxObjectSize() )
|
||||
{
|
||||
DefaultDeallocator( p );
|
||||
return;
|
||||
}
|
||||
assert( NULL != pool_ );
|
||||
if ( 0 == numBytes ) numBytes = 1;
|
||||
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
||||
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||
assert( index < allocCount );
|
||||
FixedAllocator & allocator = pool_[ index ];
|
||||
assert( allocator.BlockSize() >= numBytes );
|
||||
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
||||
const bool found = allocator.Deallocate( p, true );
|
||||
assert( found );
|
||||
}
|
||||
|
||||
}; // end namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// March 20: fix exception safety issue in FixedAllocator::Allocate
|
||||
// (thanks to Chris Udazvinis for pointing that out)
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Aug 02, 2002: Fix in VicinityFind sent by Pavel Vozenilek
|
||||
// Nov 26, 2004: Re-implemented by Rich Sposato.
|
||||
// Jun 22, 2005: Fix in FixedAllocator::Allocate by Chad Lehman
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Log$
|
||||
// Revision 1.1 2005/07/20 08:40:01 syntheticpp
|
||||
// move directory: MSVC->include/noncc
|
||||
//
|
||||
// Revision 1.9 2005/07/20 00:34:15 rich_sposato
|
||||
// Fixed overflow bug in calculating number of blocks per Chunk.
|
||||
//
|
165
include/noncc/MSVC/1300/SmallObj.h
Executable file
165
include/noncc/MSVC/1300/SmallObj.h
Executable file
|
@ -0,0 +1,165 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Wesley Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Nov 26, 2004
|
||||
|
||||
#ifndef SMALLOBJ_INC_
|
||||
#define SMALLOBJ_INC_
|
||||
|
||||
#include "Threads.h"
|
||||
#include "Singleton.h"
|
||||
#include <cstddef>
|
||||
#include <new> // needed for std::nothrow_t parameter.
|
||||
|
||||
#ifndef DEFAULT_CHUNK_SIZE
|
||||
#define DEFAULT_CHUNK_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef MAX_SMALL_OBJECT_SIZE
|
||||
#define MAX_SMALL_OBJECT_SIZE 256
|
||||
#endif
|
||||
|
||||
#ifndef LOKI_DEFAULT_OBJECT_ALIGNMENT
|
||||
#define LOKI_DEFAULT_OBJECT_ALIGNMENT 4
|
||||
#endif
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
class FixedAllocator;
|
||||
|
||||
class SmallObjAllocator
|
||||
{
|
||||
public:
|
||||
SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize,
|
||||
std::size_t objectAlignSize );
|
||||
|
||||
~SmallObjAllocator( void );
|
||||
|
||||
void * Allocate( std::size_t size, bool doThrow );
|
||||
|
||||
void Deallocate( void * p, std::size_t size );
|
||||
|
||||
inline std::size_t GetMaxObjectSize() const { return maxSmallObjectSize_; }
|
||||
|
||||
inline std::size_t GetAlignment() const { return objectAlignSize_; }
|
||||
|
||||
private:
|
||||
Loki::FixedAllocator * pool_;
|
||||
|
||||
std::size_t maxSmallObjectSize_;
|
||||
|
||||
std::size_t objectAlignSize_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SmallObject
|
||||
// Base class for polymorphic small objects, offers fast allocations &
|
||||
// deallocations. Destructor is virtual and public.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
template <class> class ThreadingModel = DEFAULT_THREADING,
|
||||
std::size_t chunkSize = DEFAULT_CHUNK_SIZE,
|
||||
std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE,
|
||||
std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT
|
||||
>
|
||||
class SmallObject : public ThreadingModel<
|
||||
SmallObject< ThreadingModel, chunkSize, maxSmallObjectSize, objectAlignSize > >
|
||||
{
|
||||
|
||||
typedef ThreadingModel< SmallObject<ThreadingModel,
|
||||
chunkSize, maxSmallObjectSize, objectAlignSize > > MyThreadingModel;
|
||||
|
||||
struct MySmallObjAllocator : public SmallObjAllocator
|
||||
{
|
||||
MySmallObjAllocator()
|
||||
: SmallObjAllocator( chunkSize, maxSmallObjectSize, objectAlignSize )
|
||||
{}
|
||||
};
|
||||
// The typedef below would make things much simpler,
|
||||
// but MWCW won't like it
|
||||
// typedef SingletonHolder<MySmallObjAllocator/*, CreateStatic,
|
||||
// NoDestroy, ThreadingModel*/> MyAllocator;
|
||||
|
||||
public:
|
||||
|
||||
#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0) && (LOKI_DEFAULT_OBJECT_ALIGNMENT != 0)
|
||||
|
||||
/// Throwing single-object new.
|
||||
static void * operator new ( std::size_t size ) throw ( std::bad_alloc )
|
||||
{
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
return SingletonHolder< MySmallObjAllocator, CreateStatic,
|
||||
NoDestroy >::Instance().Allocate( size, true );
|
||||
}
|
||||
|
||||
/// Non-throwing single-object new.
|
||||
static void * operator new ( std::size_t size, const std::nothrow_t & ) throw ()
|
||||
{
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
return SingletonHolder< MySmallObjAllocator, CreateStatic,
|
||||
NoDestroy >::Instance().Allocate( size, false );
|
||||
}
|
||||
|
||||
/// Placement single-object new.
|
||||
static void * operator new ( std::size_t size, void * place )
|
||||
{
|
||||
return ::operator new( size, place );
|
||||
}
|
||||
|
||||
/// Single-object delete.
|
||||
static void operator delete ( void * p, std::size_t size ) throw ()
|
||||
{
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
SingletonHolder< MySmallObjAllocator, CreateStatic,
|
||||
NoDestroy >::Instance().Deallocate( p, size );
|
||||
}
|
||||
|
||||
/// Non-throwing single-object delete.
|
||||
static void operator delete ( void * p, std::size_t size,
|
||||
const std::nothrow_t & ) throw()
|
||||
{
|
||||
typename MyThreadingModel::Lock lock;
|
||||
(void)lock; // get rid of warning
|
||||
SingletonHolder< MySmallObjAllocator, CreateStatic,
|
||||
NoDestroy >::Instance().Deallocate( p, size );
|
||||
}
|
||||
|
||||
/// Placement single-object delete.
|
||||
static void operator delete ( void * p, void * place )
|
||||
{
|
||||
::operator delete ( p, place );
|
||||
}
|
||||
|
||||
#endif // #if default template parameters are not zero
|
||||
|
||||
virtual ~SmallObject() {}
|
||||
}; // end class SmallObject
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// Nov. 26, 2004: re-implemented by Rich Sposato.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // SMALLOBJ_INC_
|
||||
|
1331
include/noncc/MSVC/1300/SmartPtr.h
Executable file
1331
include/noncc/MSVC/1300/SmartPtr.h
Executable file
File diff suppressed because it is too large
Load diff
199
include/noncc/MSVC/1300/Threads.h
Executable file
199
include/noncc/MSVC/1300/Threads.h
Executable file
|
@ -0,0 +1,199 @@
|
|||
#ifndef THREADS_H_
|
||||
#define THREADS_H_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro DEFAULT_THREADING
|
||||
// Selects the default threading model for certain components of Loki
|
||||
// If you don't define it, it defaults to single-threaded
|
||||
// All classes in Loki have configurable threading model; DEFAULT_THREADING
|
||||
// affects only default template arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef DEFAULT_THREADING
|
||||
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
||||
#endif
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SingleThreaded
|
||||
// Implementation of the ThreadingModel policy used by various classes
|
||||
// Implements a single-threaded model; no synchronization
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Host>
|
||||
class SingleThreaded
|
||||
{
|
||||
public:
|
||||
struct Lock
|
||||
{
|
||||
Lock() {}
|
||||
explicit Lock(const SingleThreaded&) {}
|
||||
};
|
||||
|
||||
typedef Host VolatileType;
|
||||
|
||||
typedef int IntType;
|
||||
|
||||
static IntType AtomicAdd(volatile IntType& lval, IntType val)
|
||||
{ return lval += val; }
|
||||
|
||||
static IntType AtomicSubtract(volatile IntType& lval, IntType val)
|
||||
{ return lval -= val; }
|
||||
|
||||
static IntType AtomicMultiply(volatile IntType& lval, IntType val)
|
||||
{ return lval *= val; }
|
||||
|
||||
static IntType AtomicDivide(volatile IntType& lval, IntType val)
|
||||
{ return lval /= val; }
|
||||
|
||||
static IntType AtomicIncrement(volatile IntType& lval)
|
||||
{ return ++lval; }
|
||||
|
||||
static IntType AtomicDecrement(volatile IntType& lval)
|
||||
{ return --lval; }
|
||||
|
||||
static void AtomicAssign(volatile IntType & lval, IntType val)
|
||||
{ lval = val; }
|
||||
|
||||
static void AtomicAssign(IntType & lval, volatile IntType & val)
|
||||
{ lval = val; }
|
||||
};
|
||||
|
||||
#ifdef _WINDOWS_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ObjectLevelLockable
|
||||
// Implementation of the ThreadingModel policy used by various classes
|
||||
// Implements a object-level locking scheme
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Host>
|
||||
class ObjectLevelLockable
|
||||
{
|
||||
mutable CRITICAL_SECTION mtx_;
|
||||
|
||||
public:
|
||||
ObjectLevelLockable()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
~ObjectLevelLockable()
|
||||
{
|
||||
::DeleteCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
class Lock;
|
||||
friend class Lock;
|
||||
|
||||
class Lock
|
||||
{
|
||||
ObjectLevelLockable const& host_;
|
||||
|
||||
Lock(const Lock&);
|
||||
Lock& operator=(const Lock&);
|
||||
public:
|
||||
|
||||
explicit Lock(const ObjectLevelLockable& host) : host_(host)
|
||||
{
|
||||
::EnterCriticalSection(&host_.mtx_);
|
||||
}
|
||||
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&host_.mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
typedef volatile Host VolatileType;
|
||||
|
||||
typedef LONG IntType;
|
||||
|
||||
static IntType AtomicIncrement(volatile IntType& lval)
|
||||
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static IntType AtomicDecrement(volatile IntType& lval)
|
||||
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static void AtomicAssign(volatile IntType& lval, IntType val)
|
||||
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
|
||||
|
||||
static void AtomicAssign(IntType& lval, volatile IntType& val)
|
||||
{ InterlockedExchange(&lval, val); }
|
||||
};
|
||||
|
||||
template <class Host>
|
||||
class ClassLevelLockable
|
||||
{
|
||||
struct Initializer
|
||||
{
|
||||
CRITICAL_SECTION mtx_;
|
||||
|
||||
Initializer()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
}
|
||||
~Initializer()
|
||||
{
|
||||
::DeleteCriticalSection(&mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
static Initializer initializer_;
|
||||
|
||||
public:
|
||||
class Lock;
|
||||
friend class Lock;
|
||||
|
||||
class Lock
|
||||
{
|
||||
Lock(const Lock&);
|
||||
Lock& operator=(const Lock&);
|
||||
public:
|
||||
Lock()
|
||||
{
|
||||
::EnterCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
explicit Lock(const ClassLevelLockable&)
|
||||
{
|
||||
::EnterCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
typedef volatile Host VolatileType;
|
||||
|
||||
typedef LONG IntType;
|
||||
|
||||
static IntType AtomicIncrement(volatile IntType& lval)
|
||||
{ return InterlockedIncrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static IntType AtomicDecrement(volatile IntType& lval)
|
||||
{ return InterlockedDecrement(&const_cast<IntType&>(lval)); }
|
||||
|
||||
static void AtomicAssign(volatile IntType& lval, IntType val)
|
||||
{ InterlockedExchange(&const_cast<IntType&>(lval), val); }
|
||||
|
||||
static void AtomicAssign(IntType& lval, volatile IntType& val)
|
||||
{ InterlockedExchange(&lval, val); }
|
||||
};
|
||||
|
||||
template <class Host>
|
||||
typename ClassLevelLockable<Host>::Initializer
|
||||
ClassLevelLockable<Host>::initializer_;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
245
include/noncc/MSVC/1300/TypeManip.h
Executable file
245
include/noncc/MSVC/1300/TypeManip.h
Executable file
|
@ -0,0 +1,245 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
#ifndef TYPEMANIP_INC_
|
||||
#define TYPEMANIP_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Int2Type
|
||||
// Converts each integral constant into a unique type
|
||||
// Invocation: Int2Type<v> where v is a compile-time constant integral
|
||||
// Defines 'value', an enum that evaluates to v
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <int v>
|
||||
struct Int2Type
|
||||
{
|
||||
enum { value = v };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Type2Type
|
||||
// Converts each type into a unique, insipid type
|
||||
// Invocation Type2Type<T> where T is a type
|
||||
// Defines the type OriginalType which maps back to T
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct Type2Type
|
||||
{
|
||||
typedef T OriginalType;
|
||||
Type2Type(){} // VC7
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Select
|
||||
// Selects one of two types based upon a boolean constant
|
||||
// Invocation: Select<flag, T, U>::Result
|
||||
// where:
|
||||
// flag is a compile-time boolean constant
|
||||
// T and U are types
|
||||
// Result evaluates to T if flag is true, and to U otherwise.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool flag, typename T, typename U>
|
||||
struct Select
|
||||
{
|
||||
private:
|
||||
template<bool>
|
||||
struct In
|
||||
{ typedef T Result; };
|
||||
|
||||
template<>
|
||||
struct In<false>
|
||||
{ typedef U Result; };
|
||||
|
||||
public:
|
||||
typedef typename In<flag>::Result Result;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsSameType
|
||||
// Return true iff two given types are the same
|
||||
// Invocation: IsSameType<T, U>::value
|
||||
// where:
|
||||
// T and U are types
|
||||
// Result evaluates to true iff U == T (types equal)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename U>
|
||||
struct IsSameType
|
||||
{
|
||||
private:
|
||||
template<typename>
|
||||
struct In
|
||||
{ enum { value = false }; };
|
||||
|
||||
template<>
|
||||
struct In<T>
|
||||
{ enum { value = true }; };
|
||||
|
||||
public:
|
||||
enum { value = In<U>::value };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
typedef char Small;
|
||||
class Big { char dummy[2]; };
|
||||
|
||||
template<typename T>
|
||||
struct IsVoid
|
||||
{
|
||||
enum { result =
|
||||
IsSameType<T, void>::value ||
|
||||
IsSameType<T, const void>::value ||
|
||||
IsSameType<T, volatile void>::value ||
|
||||
IsSameType<T, const volatile void>::value
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// is one type convertable to another?
|
||||
//
|
||||
template <class T, class U>
|
||||
class is_convertible
|
||||
{
|
||||
struct VoidReplace {};
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
Private::IsVoid<T>::result,
|
||||
VoidReplace, T
|
||||
>
|
||||
::Result T1;
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
Private::IsVoid<U>::result,
|
||||
VoidReplace, U
|
||||
>
|
||||
::Result U1;
|
||||
|
||||
static Private::Big Test(...);
|
||||
static Private::Small Test(U1);
|
||||
static T1 MakeT();
|
||||
|
||||
public:
|
||||
enum { exists = sizeof(Test(MakeT())) == sizeof(Private::Small) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Conversion
|
||||
// Figures out the conversion relationships between two types
|
||||
// Invocations (T and U are types):
|
||||
// a) Conversion<T, U>::exists
|
||||
// returns (at compile time) true if there is an implicit conversion from T
|
||||
// to U (example: Derived to Base)
|
||||
// b) Conversion<T, U>::exists2Way
|
||||
// returns (at compile time) true if there are both conversions from T
|
||||
// to U and from U to T (example: int to char and back)
|
||||
// c) Conversion<T, U>::sameType
|
||||
// returns (at compile time) true if T and U represent the same type
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class U>
|
||||
struct Conversion
|
||||
{
|
||||
enum { exists = (is_convertible<T,U>::exists) };
|
||||
enum { exists2Way = (exists && is_convertible<U, T>::exists) };
|
||||
enum { sameType = (IsSameType<T, U>::value) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SuperSubclass
|
||||
// Invocation: SuperSubclass<B, D>::value where B and D are types.
|
||||
// Returns true if B is a public base of D, or if B and D are aliases of the
|
||||
// same type.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class U>
|
||||
struct SuperSubclass
|
||||
{
|
||||
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SuperSubclassStrict
|
||||
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
|
||||
// Returns true if B is a public base of D.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T,class U>
|
||||
struct SuperSubclassStrict
|
||||
{
|
||||
enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
|
||||
!::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro SUPERSUBCLASS
|
||||
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
|
||||
// Returns true if B is a public base of D, or if B and D are aliases of the
|
||||
// same type.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
// Deprecated: Use SuperSubclass class template instead.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS(T, U) \
|
||||
::Loki::SuperSubclass<T,U>::value
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro SUPERSUBCLASS_STRICT
|
||||
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
|
||||
// Returns true if B is a public base of D.
|
||||
//
|
||||
// Caveat: might not work if T and U are in a private inheritance hierarchy.
|
||||
// Deprecated: Use SuperSubclassStrict class template instead.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SUPERSUBCLASS_STRICT(T, U) \
|
||||
::Loki::SuperSubclassStrict<T,U>::value
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
// October 10, 2002: Commented IsSameType template (not a Loki-template - yet). MKH
|
||||
// October 12, 2002: Added SuperSubclass and SuperSubclassStrict templates.
|
||||
// The corresponding macros are deprecated. T.S.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPEMANIP_INC_
|
370
include/noncc/MSVC/1300/TypeTraits.h
Executable file
370
include/noncc/MSVC/1300/TypeTraits.h
Executable file
|
@ -0,0 +1,370 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: May 19, 2002
|
||||
|
||||
//TODOSGB None of the parameter types are defined inside of TypeTraits, e.g. PointeeType, ReferredType, etc...
|
||||
|
||||
#ifndef TYPETRAITS_INC_
|
||||
#define TYPETRAITS_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomUnsignedInt
|
||||
// Offers a means to integrate nonstandard built-in unsigned integral types
|
||||
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
|
||||
// class template defined below.
|
||||
// Invocation: IsCustomUnsignedInt<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
|
||||
// integral type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomUnsignedInt
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomSignedInt
|
||||
// Offers a means to integrate nonstandard built-in unsigned integral types
|
||||
// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
|
||||
// class template defined below.
|
||||
// Invocation: IsCustomSignedInt<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in signed
|
||||
// integral type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomSignedInt
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsCustomFloat
|
||||
// Offers a means to integrate nonstandard floating point types with the
|
||||
// TypeTraits class template defined below.
|
||||
// Invocation: IsCustomFloat<T> where T is any type
|
||||
// Defines 'value', an enum that is 1 iff T is a custom built-in
|
||||
// floating point type
|
||||
// Specialize this class template for nonstandard unsigned integral types
|
||||
// and define value = 1 in those specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct IsCustomFloat
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types for class template TypeTraits defined below
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Private
|
||||
{
|
||||
typedef TYPELIST_4(unsigned char, unsigned short int,
|
||||
unsigned int, unsigned long int) StdUnsignedInts;
|
||||
typedef TYPELIST_4(signed char, short int,
|
||||
int, long int) StdSignedInts;
|
||||
typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts;
|
||||
typedef TYPELIST_3(float, double, long double) StdFloats;
|
||||
}
|
||||
|
||||
namespace Private
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class IsArray
|
||||
{
|
||||
template <typename> struct Type2Type2 {};
|
||||
|
||||
typedef char (&yes)[1];
|
||||
typedef char (&no) [2];
|
||||
|
||||
template<typename U, size_t N>
|
||||
static void vc7_need_this_for_is_array(Type2Type2<U(*)[N]>);
|
||||
|
||||
template<typename U, size_t N>
|
||||
static yes is_array1(Type2Type2<U[N]>*);
|
||||
static no is_array1(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_array2(Type2Type2<U[]>*);
|
||||
static no is_array2(...);
|
||||
|
||||
public:
|
||||
enum {
|
||||
value =
|
||||
sizeof(is_array1((Type2Type2<T>*)0)) == sizeof(yes) ||
|
||||
sizeof(is_array2((Type2Type2<T>*)0)) == sizeof(yes)
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // Private Namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template TypeTraits
|
||||
// Figures out various properties of any given type
|
||||
// Invocations (T is a type):
|
||||
// a) TypeTraits<T>::isPointer
|
||||
// returns (at compile time) true if T is a pointer type
|
||||
// b) TypeTraits<T>::PointeeType
|
||||
// returns the type to which T points is T is a pointer type, NullType otherwise
|
||||
// a) TypeTraits<T>::isReference
|
||||
// returns (at compile time) true if T is a reference type
|
||||
// b) TypeTraits<T>::ReferredType
|
||||
// returns the type to which T refers is T is a reference type, NullType
|
||||
// otherwise
|
||||
// c) TypeTraits<T>::isMemberPointer
|
||||
// returns (at compile time) true if T is a pointer to member type
|
||||
// d) TypeTraits<T>::isStdUnsignedInt
|
||||
// returns (at compile time) true if T is a standard unsigned integral type
|
||||
// e) TypeTraits<T>::isStdSignedInt
|
||||
// returns (at compile time) true if T is a standard signed integral type
|
||||
// f) TypeTraits<T>::isStdIntegral
|
||||
// returns (at compile time) true if T is a standard integral type
|
||||
// g) TypeTraits<T>::isStdFloat
|
||||
// returns (at compile time) true if T is a standard floating-point type
|
||||
// h) TypeTraits<T>::isStdArith
|
||||
// returns (at compile time) true if T is a standard arithmetic type
|
||||
// i) TypeTraits<T>::isStdFundamental
|
||||
// returns (at compile time) true if T is a standard fundamental type
|
||||
// j) TypeTraits<T>::isUnsignedInt
|
||||
// returns (at compile time) true if T is a unsigned integral type
|
||||
// k) TypeTraits<T>::isSignedInt
|
||||
// returns (at compile time) true if T is a signed integral type
|
||||
// l) TypeTraits<T>::isIntegral
|
||||
// returns (at compile time) true if T is a integral type
|
||||
// m) TypeTraits<T>::isFloat
|
||||
// returns (at compile time) true if T is a floating-point type
|
||||
// n) TypeTraits<T>::isArith
|
||||
// returns (at compile time) true if T is a arithmetic type
|
||||
// o) TypeTraits<T>::isFundamental
|
||||
// returns (at compile time) true if T is a fundamental type
|
||||
// p) TypeTraits<T>::ParameterType
|
||||
// returns the optimal type to be used as a parameter for functions that take Ts
|
||||
// q) TypeTraits<T>::isConst
|
||||
// returns (at compile time) true if T is a const-qualified type
|
||||
// r) TypeTraits<T>::NonConstType
|
||||
// removes the 'const' qualifier from T, if any
|
||||
// s) TypeTraits<T>::isVolatile
|
||||
// returns (at compile time) true if T is a volatile-qualified type
|
||||
// t) TypeTraits<T>::NonVolatileType
|
||||
// removes the 'volatile' qualifier from T, if any
|
||||
// u) TypeTraits<T>::UnqualifiedType
|
||||
// removes both the 'const' and 'volatile' qualifiers from T, if any
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
class TypeTraits
|
||||
{
|
||||
typedef char (&yes)[1];
|
||||
typedef char (&no) [2];
|
||||
|
||||
template<typename U>
|
||||
static yes is_reference(Type2Type<U&>);
|
||||
static no is_reference(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_pointer1(Type2Type<U*>);
|
||||
static no is_pointer1(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_pointer2(Type2Type<U const *>);
|
||||
static no is_pointer2(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_pointer3(Type2Type<U volatile *>);
|
||||
static no is_pointer3(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_pointer4(Type2Type<U const volatile *>);
|
||||
static no is_pointer4(...);
|
||||
|
||||
template<typename U, typename V>
|
||||
static yes is_pointer2member(Type2Type<U V::*>);
|
||||
static no is_pointer2member(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_const(Type2Type<const U>);
|
||||
static no is_const(...);
|
||||
|
||||
template<typename U>
|
||||
static yes is_volatile(Type2Type<volatile U>);
|
||||
static no is_volatile(...);
|
||||
|
||||
public:
|
||||
//
|
||||
// VC7 BUG - will not detect reference to function
|
||||
//
|
||||
enum {
|
||||
isReference =
|
||||
sizeof(is_reference(Type2Type<T>())) == sizeof(yes)
|
||||
};
|
||||
|
||||
//
|
||||
// VC7 BUG - will not detect pointer to function
|
||||
//
|
||||
enum {
|
||||
isPointer =
|
||||
sizeof(is_pointer1(Type2Type<T>())) == sizeof(yes) ||
|
||||
sizeof(is_pointer2(Type2Type<T>())) == sizeof(yes) ||
|
||||
sizeof(is_pointer3(Type2Type<T>())) == sizeof(yes) ||
|
||||
sizeof(is_pointer4(Type2Type<T>())) == sizeof(yes)
|
||||
};
|
||||
|
||||
enum {
|
||||
isMemberPointer =
|
||||
sizeof(is_pointer2member(Type2Type<T>())) == sizeof(yes)
|
||||
};
|
||||
|
||||
enum {
|
||||
isArray = Private::IsArray<T>::value
|
||||
};
|
||||
|
||||
enum {
|
||||
isVoid =
|
||||
IsSameType<T, void>::value ||
|
||||
IsSameType<T, const void>::value ||
|
||||
IsSameType<T, volatile void>::value ||
|
||||
IsSameType<T, const volatile void>::value
|
||||
};
|
||||
|
||||
enum { isStdUnsignedInt =
|
||||
TL::IndexOf<Private::StdUnsignedInts, T>::value >= 0 };
|
||||
enum { isStdSignedInt =
|
||||
TL::IndexOf<Private::StdSignedInts, T>::value >= 0 };
|
||||
enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
|
||||
TL::IndexOf<Private::StdOtherInts, T>::value >= 0 };
|
||||
enum { isStdFloat = TL::IndexOf<Private::StdFloats, T>::value >= 0 };
|
||||
enum { isStdArith = isStdIntegral || isStdFloat };
|
||||
enum { isStdFundamental = isStdArith || isStdFloat || isVoid };
|
||||
|
||||
enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<T>::value };
|
||||
enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<T>::value };
|
||||
enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
|
||||
enum { isFloat = isStdFloat || IsCustomFloat<T>::value };
|
||||
enum { isArith = isIntegral || isFloat };
|
||||
enum { isFundamental = isStdFundamental || isArith || isFloat };
|
||||
|
||||
enum {
|
||||
isConst =
|
||||
sizeof(is_const(Type2Type<T>())) == sizeof(yes)
|
||||
};
|
||||
|
||||
enum {
|
||||
isVolatile =
|
||||
sizeof(is_volatile(Type2Type<T>())) == sizeof(yes)
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// is_scalar include functions types
|
||||
struct is_scalar
|
||||
{
|
||||
private:
|
||||
struct BoolConvert { BoolConvert(bool); };
|
||||
|
||||
static yes check(BoolConvert);
|
||||
static no check(...);
|
||||
|
||||
struct NotScalar {};
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isVoid || isReference || isArray,
|
||||
NotScalar, T
|
||||
>
|
||||
::Result RetType;
|
||||
|
||||
static RetType& get();
|
||||
|
||||
public:
|
||||
//
|
||||
// Ignore forcing value to bool 'true' or 'false' (performance warning)
|
||||
//
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4800)
|
||||
#endif
|
||||
|
||||
enum { value = sizeof(check(get())) == sizeof(yes) };
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default: 4800)
|
||||
#endif
|
||||
}; // is_scalar
|
||||
|
||||
|
||||
private:
|
||||
template<bool IsRef>
|
||||
struct AdjReference
|
||||
{
|
||||
template<typename U>
|
||||
struct In { typedef U const & Result; };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AdjReference<true>
|
||||
{
|
||||
template<typename U>
|
||||
struct In { typedef U Result; };
|
||||
};
|
||||
|
||||
typedef typename AdjReference<isReference || isVoid>::
|
||||
template In<T>::Result AdjType;
|
||||
|
||||
public:
|
||||
enum { isScalar = is_scalar::value };
|
||||
|
||||
|
||||
typedef typename Select
|
||||
<
|
||||
isScalar || isArray, T, AdjType
|
||||
>
|
||||
::Result ParameterType;
|
||||
|
||||
//
|
||||
// We get is_class for free
|
||||
// BUG - fails with functions types (ICE) and unknown size array
|
||||
// (but works for other incomplete types)
|
||||
// (the boost one (Paul Mensonides) is better)
|
||||
//
|
||||
enum { isClass =
|
||||
!isScalar &&
|
||||
!isArray &&
|
||||
!isReference &&
|
||||
!isVoid
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPETRAITS_INC_
|
1062
include/noncc/MSVC/1300/Typelist.h
Executable file
1062
include/noncc/MSVC/1300/Typelist.h
Executable file
File diff suppressed because it is too large
Load diff
106
include/noncc/MSVC/1300/VC_Alignment.h
Executable file
106
include/noncc/MSVC/1300/VC_Alignment.h
Executable file
|
@ -0,0 +1,106 @@
|
|||
// Last update: June 20, 2001
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#else
|
||||
# error "Visual C++ specific header !"
|
||||
#endif
|
||||
|
||||
#ifndef VC_ALIGNMENT_INC_
|
||||
#define VC_ALIGNMENT_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "static_check.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template MaxAlign
|
||||
// Computes the maximum alignof for all types in a typelist
|
||||
// Usage: MaxAlign<TList>::result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList> struct VC_MaxAlign;
|
||||
|
||||
template <>
|
||||
struct VC_MaxAlign< ::Loki::NullType >
|
||||
{
|
||||
enum { result = 0 };
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
struct VC_MaxAlign
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
private:
|
||||
enum { headResult = __alignof(Head) };
|
||||
enum { tailResult = VC_MaxAlign<Tail>::result };
|
||||
|
||||
public:
|
||||
enum { result = headResult > tailResult ?
|
||||
headResult : tailResult };
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class VC_AlignedPODBase
|
||||
// Defines a host of protected types used by VC_AlignedPOD (defined later)
|
||||
// Could be just part of VC_AlignedPOD itself, but making it separate ought to
|
||||
// reduce compile times
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class VC_AlignedPODBase
|
||||
{
|
||||
protected:
|
||||
|
||||
template<unsigned AlignmentSize>
|
||||
struct AlignedPod
|
||||
{
|
||||
STATIC_CHECK(AlignmentSize == 0, BadAlignmentSize_OnlyUpTo128);
|
||||
};
|
||||
|
||||
//
|
||||
// I used the macro because align(#)
|
||||
// only works with Integer literals
|
||||
//
|
||||
#define ALIGNED_POD(_size_) \
|
||||
template<> struct AlignedPod<_size_> { \
|
||||
__declspec(align(_size_)) struct type { char X[_size_]; }; \
|
||||
enum { alignment = __alignof(type) }; }; \
|
||||
STATIC_CHECK((_size_ == sizeof(AlignedPod<_size_>::type)), SizeofNotEqualSize); \
|
||||
STATIC_CHECK((_size_ == (AlignedPod<_size_>::alignment)), SizeofNotEqualAlignof)
|
||||
|
||||
|
||||
ALIGNED_POD(1);
|
||||
ALIGNED_POD(2);
|
||||
ALIGNED_POD(4);
|
||||
ALIGNED_POD(8);
|
||||
ALIGNED_POD(16);
|
||||
ALIGNED_POD(32);
|
||||
ALIGNED_POD(64);
|
||||
ALIGNED_POD(128);
|
||||
// can be up to 8192 - is it realistic?
|
||||
|
||||
#undef ALIGNED_POD
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template VC_AlignedPOD
|
||||
// Computes the alignment of all types in a typelist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TList>
|
||||
class VC_AlignedPOD : VC_AlignedPODBase
|
||||
{
|
||||
enum { maxAlign = VC_MaxAlign<TList>::result };
|
||||
|
||||
public:
|
||||
typedef typename AlignedPod<maxAlign>::type Result;
|
||||
};
|
||||
|
||||
#endif // VC_ALIGNMENT_INC_
|
||||
|
864
include/noncc/MSVC/1300/Variant.h
Executable file
864
include/noncc/MSVC/1300/Variant.h
Executable file
|
@ -0,0 +1,864 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2001, 2002 by Andrei Alexandrescu
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VARIANT_INC_
|
||||
#define VARIANT_INC_
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include "Visitor.h"
|
||||
#include "Typelist.h"
|
||||
#include "static_check.h"
|
||||
|
||||
//
|
||||
// At the moment there is no namespace for Variant
|
||||
//
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "VC_Alignment.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConfigurableUnion
|
||||
// Builds a union that contains each type in a typelist
|
||||
// Usage: ConfigurableUnion<TList> is the very type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class U> union ConfigurableUnion;
|
||||
|
||||
template <> union ConfigurableUnion< ::Loki::NullType >
|
||||
{
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
union ConfigurableUnion
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
public:
|
||||
Head head_;
|
||||
ConfigurableUnion<Tail> tail_;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template MaxSize
|
||||
// Computes the maximum sizeof for all types in a typelist
|
||||
// Usage: MaxSize<TList>::result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList> struct MaxSize;
|
||||
|
||||
template <>
|
||||
struct MaxSize< ::Loki::NullType >
|
||||
{
|
||||
enum { result = 0 };
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
struct MaxSize
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
private:
|
||||
enum { headResult = sizeof(Head) };
|
||||
enum { tailResult = MaxSize<Tail>::result };
|
||||
|
||||
public:
|
||||
enum { result = headResult > tailResult ?
|
||||
headResult : tailResult };
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class AlignedPODBase
|
||||
// Defines a host of protected types used by AlignedPOD (defined later)
|
||||
// Could be just part of AlignedPOD itself, but making it separate ought to
|
||||
// reduce compile times
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AlignedPODBase
|
||||
{
|
||||
protected:
|
||||
template <class TList, std::size_t size>
|
||||
struct ComputeAlignBound
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
private:
|
||||
template<class TList1>
|
||||
struct In
|
||||
{
|
||||
private:
|
||||
typedef typename TList1::Head Head1;
|
||||
typedef typename TList1::Tail Tail1;
|
||||
|
||||
typedef typename ComputeAlignBound<Tail1, size>::Result TailResult;
|
||||
|
||||
public:
|
||||
typedef typename ::Loki::Select
|
||||
<
|
||||
sizeof(Head1) <= size,
|
||||
::Loki::Typelist<Head1, TailResult>,
|
||||
TailResult
|
||||
>
|
||||
::Result Result;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct In< ::Loki::NullType >
|
||||
{
|
||||
typedef ::Loki::NullType Result;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename In<TList>::Result Result;
|
||||
};
|
||||
|
||||
template <typename U> struct Structify
|
||||
{ U dummy_; };
|
||||
|
||||
class Unknown;
|
||||
|
||||
// VC7: fatal error C1067: compiler limit :
|
||||
// debug information module size exceeded
|
||||
// Therfore I decreased the list to 26 without
|
||||
// changing the rage of detectable alignment
|
||||
typedef TYPELIST_26(
|
||||
char,
|
||||
wchar_t,
|
||||
short int,
|
||||
int,
|
||||
long int,
|
||||
float,
|
||||
double,
|
||||
long double,
|
||||
char*,
|
||||
void*,
|
||||
Unknown (*)(Unknown),
|
||||
Unknown* Unknown::*,
|
||||
Unknown (Unknown::*)(Unknown),
|
||||
Structify<char>,
|
||||
Structify<wchar_t>,
|
||||
Structify<short int>,
|
||||
Structify<int>,
|
||||
Structify<long int>,
|
||||
Structify<float>,
|
||||
Structify<double>,
|
||||
Structify<long double>,
|
||||
Structify<char*>,
|
||||
Structify<void*>,
|
||||
Structify<Unknown (*)(Unknown)>,
|
||||
Structify<Unknown* Unknown::*>,
|
||||
Structify<Unknown (Unknown::*)(Unknown)>
|
||||
)
|
||||
TypesOfAllAlignments;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template AlignedPOD
|
||||
// Computes the alignment of all types in a typelist
|
||||
// Usage: ConfigurableUnion<TList> is the very type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TList>
|
||||
class AlignedPOD : private AlignedPODBase
|
||||
{
|
||||
enum { maxSize = MaxSize<TList>::result };
|
||||
|
||||
typedef typename ComputeAlignBound
|
||||
<
|
||||
TypesOfAllAlignments,
|
||||
maxSize
|
||||
>
|
||||
::Result AlignTypes;
|
||||
|
||||
public:
|
||||
typedef ConfigurableUnion<AlignTypes> Result;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template MakeConst
|
||||
// Given a typelist TList, returns a typelist that contains the types in TList
|
||||
// adding a const qualifier to each.
|
||||
// Usage: MakeConst<TList>::Result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList> struct MakeConst;
|
||||
|
||||
template <> struct MakeConst< ::Loki::NullType >
|
||||
{
|
||||
typedef ::Loki::NullType Result; // terminator is not const
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
struct MakeConst
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
private:
|
||||
typedef typename MakeConst<Tail>::Result NewTail;
|
||||
|
||||
public:
|
||||
typedef ::Loki::Typelist<const Head, NewTail> Result;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Converter
|
||||
// Supports the Variant-to-Variant conversion constructor
|
||||
// Guaranteed to issue an internal compiler error on:
|
||||
// 1. Metrowerks CodeWarrior 7.0 (internal compiler error: File:
|
||||
// 'CTemplateTools.c' Line: 1477
|
||||
// Variant.h line 244 UnitBase > VisitorBase;)
|
||||
// 2. Microsoft Visual C++ 7.1 alpha release (Assertion failed:
|
||||
// ( name - nameBuf ) < LIMIT_ID_LENGTH,
|
||||
// file f:\vs70builds\2108\vc\Compiler\CxxFE\sl\P1\C\outdname.c,
|
||||
// line 4583)
|
||||
// 3. GNU gcc 2.95.3-6 (Internal compiler error 980422)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class VariantFrom, class VariantTo>
|
||||
struct Converter
|
||||
{
|
||||
//private: VC7 complains
|
||||
struct UnitBase : public VariantFrom::ConstStrictVisitor
|
||||
{
|
||||
protected:
|
||||
VariantTo* storageForDestination;
|
||||
};
|
||||
|
||||
template <class Type, class Base>
|
||||
struct Unit : public Base
|
||||
{
|
||||
private:
|
||||
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||
{
|
||||
new(this->storageForDestination) VariantTo(obj);
|
||||
}
|
||||
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||
{
|
||||
throw std::runtime_error("Cannot convert");
|
||||
}
|
||||
virtual void Visit(const Type& obj)
|
||||
{
|
||||
using namespace Loki;
|
||||
typedef typename VariantTo::Types TList;
|
||||
enum { dispatch = TL::IndexOf<TList, Type>::value > -1 };
|
||||
this->DoVisit(obj, Int2Type<dispatch>());
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef ::Loki::GenLinearHierarchy
|
||||
<
|
||||
typename VariantFrom::Types,
|
||||
Unit,
|
||||
UnitBase
|
||||
>
|
||||
VisitorBase;
|
||||
|
||||
public:
|
||||
struct Visitor : public VisitorBase
|
||||
{
|
||||
explicit Visitor(VariantTo& dest)
|
||||
{
|
||||
// Initialize the pointer to destination
|
||||
this->storageForDestination = &dest;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ConverterTo
|
||||
// Supports Variant-to-T conversion
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
template <class VariantFrom, class T>
|
||||
struct ConverterTo
|
||||
{
|
||||
private:
|
||||
struct DestHolder
|
||||
: VariantFrom::ConstStrictVisitor
|
||||
{
|
||||
protected:
|
||||
DestHolder() {}
|
||||
DestHolder(const T& dest) : destination_(dest) {}
|
||||
T destination_;
|
||||
};
|
||||
|
||||
template <class TList>
|
||||
struct VisitorBase
|
||||
: VisitorBase<typename TList::Tail>
|
||||
{
|
||||
private:
|
||||
ASSERT_TYPELIST(TList);
|
||||
|
||||
typedef typename TList::Head Type;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
protected:
|
||||
VisitorBase<TList>() {}
|
||||
VisitorBase<TList>(const T& dest)
|
||||
: VisitorBase<Tail>(dest) {}
|
||||
|
||||
private:
|
||||
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||
{ //
|
||||
// T temp(obj)
|
||||
// swap(destination_, temp) or destination_ = temp
|
||||
//
|
||||
this->destination_ = obj;
|
||||
}
|
||||
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||
{
|
||||
throw std::runtime_error("Cannot convert");
|
||||
}
|
||||
|
||||
virtual void Visit(const Type& obj)
|
||||
{
|
||||
using namespace Loki;
|
||||
enum { dispatch = Conversion<Type, T>::exists != 0 };
|
||||
this->DoVisit(obj, Int2Type<dispatch>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VisitorBase< ::Loki::NullType >
|
||||
: DestHolder
|
||||
{
|
||||
protected:
|
||||
VisitorBase< ::Loki::NullType >() {}
|
||||
VisitorBase< ::Loki::NullType >(const T& dest)
|
||||
: DestHolder(dest) {}
|
||||
};
|
||||
|
||||
|
||||
typedef VisitorBase
|
||||
<
|
||||
typename VariantFrom::Types
|
||||
>
|
||||
VisitorBaseType;
|
||||
|
||||
public:
|
||||
struct Visitor : public VisitorBaseType
|
||||
{
|
||||
Visitor() {}
|
||||
|
||||
explicit Visitor(const T& dest)
|
||||
: VisitorBaseType(dest) {}
|
||||
|
||||
const T &GetDestination() const
|
||||
{ return this->destination_; }
|
||||
};
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <class VariantFrom, class T>
|
||||
struct ConverterTo
|
||||
{
|
||||
//private:
|
||||
struct UnitBase : public VariantFrom::ConstStrictVisitor
|
||||
{
|
||||
protected:
|
||||
T destination_;
|
||||
};
|
||||
|
||||
template <class Type, class Base>
|
||||
struct Unit : public Base
|
||||
{
|
||||
private:
|
||||
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
|
||||
{
|
||||
this->destination_ = obj;
|
||||
}
|
||||
void DoVisit(const Type&, ::Loki::Int2Type<false>)
|
||||
{
|
||||
throw std::runtime_error("Cannot convert");
|
||||
}
|
||||
virtual void Visit(const Type& obj)
|
||||
{
|
||||
using namespace Loki;
|
||||
enum { dispatch = Conversion<Type, T>::exists != 0 };
|
||||
this->DoVisit(obj, Int2Type<dispatch>());
|
||||
}
|
||||
};
|
||||
|
||||
typedef ::Loki::GenLinearHierarchy<
|
||||
typename VariantFrom::Types,
|
||||
Unit,
|
||||
UnitBase > VisitorBase;
|
||||
|
||||
public:
|
||||
struct Visitor : public VisitorBase
|
||||
{
|
||||
const T &GetDestination() const
|
||||
{ return this->destination_; }
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
namespace Private
|
||||
{
|
||||
template<typename T>
|
||||
struct RawDataKeeper
|
||||
{
|
||||
private:
|
||||
typedef char RawBuffer_t[sizeof(T)];
|
||||
enum ObjectState_e { eNone, ePreConstruct, ePostConstruct };
|
||||
|
||||
T &obj_;
|
||||
ObjectState_e eObjState_;
|
||||
RawBuffer_t bufferOrg_;
|
||||
RawBuffer_t bufferNew_;
|
||||
|
||||
private:
|
||||
void SetObj(const RawBuffer_t &buf) throw()
|
||||
{
|
||||
memcpy(&reinterpret_cast<char &>(obj_), buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void GetObj(RawBuffer_t &buf) throw()
|
||||
{
|
||||
memcpy(buf, &reinterpret_cast<const char &>(obj_), sizeof(buf));
|
||||
}
|
||||
|
||||
public:
|
||||
explicit RawDataKeeper(T &obj)
|
||||
: obj_(obj), eObjState_(eNone)
|
||||
{}
|
||||
|
||||
// add const U & version ?
|
||||
template<typename U>
|
||||
void ConstructNew(U &src)
|
||||
{
|
||||
assert(eObjState_ == eNone);
|
||||
|
||||
GetObj(bufferOrg_);
|
||||
|
||||
eObjState_ = ePreConstruct;
|
||||
new (&obj_) T(src);
|
||||
eObjState_ = ePostConstruct;
|
||||
|
||||
GetObj(bufferNew_);
|
||||
SetObj(bufferOrg_);
|
||||
}
|
||||
|
||||
void SetNew() throw()
|
||||
{
|
||||
assert(eObjState_ == ePostConstruct);
|
||||
|
||||
obj_.~T();
|
||||
SetObj(bufferNew_);
|
||||
eObjState_ = eNone;
|
||||
}
|
||||
|
||||
~RawDataKeeper()
|
||||
{
|
||||
switch(eObjState_)
|
||||
{
|
||||
case ePostConstruct:
|
||||
SetObj(bufferNew_);
|
||||
obj_.~T();
|
||||
// fall
|
||||
|
||||
case ePreConstruct:
|
||||
SetObj(bufferOrg_);
|
||||
// fall
|
||||
|
||||
case eNone:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RawDataKeeper(const RawDataKeeper &);
|
||||
RawDataKeeper& operator=(const RawDataKeeper &);
|
||||
};
|
||||
|
||||
//
|
||||
// based on Eric Fridman's safe_swap from boost Variant
|
||||
//
|
||||
// strong exception-safety guarantee.
|
||||
//
|
||||
// !WARNING!
|
||||
// SafeSwap CANNOT be safely used in the general case if either
|
||||
// argument's data members may be accessed concurrently.
|
||||
//
|
||||
template<typename T>
|
||||
void SafeSwap(T &lhs, T &rhs)
|
||||
{
|
||||
typedef RawDataKeeper<T> RhsDataKeeper;
|
||||
typedef RawDataKeeper<T> LhsDataKeeper;
|
||||
|
||||
RhsDataKeeper rhsKeeper(rhs);
|
||||
rhsKeeper.ConstructNew(lhs);
|
||||
|
||||
LhsDataKeeper lhsKeeper(lhs);
|
||||
lhsKeeper.ConstructNew(rhs);
|
||||
|
||||
rhsKeeper.SetNew();
|
||||
lhsKeeper.SetNew();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// based on Eric Fridman's safe_assign from boost Variant
|
||||
//
|
||||
// strong exception-safety guarantee.
|
||||
//
|
||||
// !WARNING!
|
||||
// SafeAssign CANNOT be safely used in the general case if either
|
||||
// argument's data members may be accessed concurrently.
|
||||
//
|
||||
template<typename T, typename U>
|
||||
void SafeAssign(T &lhs, const U &src)
|
||||
{
|
||||
typedef RawDataKeeper<T> LhsDataKeeper;
|
||||
|
||||
LhsDataKeeper lhsKeeper(lhs);
|
||||
lhsKeeper.ConstructNew(src);
|
||||
lhsKeeper.SetNew();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void SwapHelper(T &lhs, T &rhs)
|
||||
{
|
||||
using namespace std;
|
||||
swap(lhs, rhs);
|
||||
}
|
||||
} // namespace Private
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template Variant
|
||||
// Implements a discriminated union in C++
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TList, class AlignedPODType = AlignedPOD<TList> >
|
||||
class Variant
|
||||
{
|
||||
// VC7: fatal error C1067: compiler limit :
|
||||
// debug information module size exceeded
|
||||
// Therfore define this type here
|
||||
typedef typename AlignedPODType::Result Align;
|
||||
|
||||
public:
|
||||
typedef TList Types;
|
||||
|
||||
// Default constructor
|
||||
// Initializes the Variant with a default-constructed object of the
|
||||
// first type in the typelist
|
||||
Variant()
|
||||
{
|
||||
typedef typename TList::Head T;
|
||||
new(&buffer_[0]) T;
|
||||
vptr_ = VTableImpl<T>::GetVPTR();
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
Variant(const Variant& rhs)
|
||||
{
|
||||
(rhs.vptr_->clone_)(rhs, *this);
|
||||
}
|
||||
|
||||
private:
|
||||
// Converting constructor; accepts any type in the typelist
|
||||
// @@@ Suggested simple improvement: accept any type convertible to one of
|
||||
// the types in the typelist. Use Loki::Conversion as a building block
|
||||
template <class T>
|
||||
void VariantConstruct(const T& val, double)
|
||||
{
|
||||
STATIC_CHECK((::Loki::TL::IndexOf<TList, T>::value >= 0),
|
||||
Invalid_Type_Used_As_Initializer);
|
||||
|
||||
new(&buffer_[0]) T(val);
|
||||
vptr_ = VTableImpl<T>::GetVPTR();
|
||||
}
|
||||
|
||||
// Inter-Variant conversion constructor
|
||||
// Current policy is: conversion succeeds iff the actual type of the source
|
||||
// is one of the types accepted by the target
|
||||
// @@@ Possible change: accept if the actual type of the source is
|
||||
// convertible to one of the types accepted by the target. Problem to
|
||||
// solve: handle ambiguities in a satisfactory manner. Suggestion: when
|
||||
// in doubt, do closest to what the compiler would do.
|
||||
template <class TList2, typename Align2>
|
||||
void VariantConstruct(const Variant<TList2, Align2>& rhs, int)
|
||||
{
|
||||
typename Converter<Variant<TList2, Align2>, Variant>::Visitor v(*this);
|
||||
typename Variant<TList2, Align2>::ConstStrictVisitor& visitor = v;
|
||||
rhs.Accept(visitor);
|
||||
}
|
||||
|
||||
public:
|
||||
// VC7 don't support partial ordering
|
||||
// The constructor initialization section
|
||||
// is empty which make it to use function instead
|
||||
// without the int = 0 the explicit seems to confuse
|
||||
// VC7 when the copy constructor should be selected
|
||||
// Crazy stuff
|
||||
template <class T>
|
||||
explicit Variant(const T& val, int = 0)
|
||||
{
|
||||
VariantConstruct(val, int(0));
|
||||
}
|
||||
|
||||
// Canonic assignment operator
|
||||
Variant& operator=(const Variant& rhs)
|
||||
{
|
||||
Private::SafeAssign(*this, rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// Assignment operator from one of the allowed types
|
||||
// This is necessary because the constructor is explicit
|
||||
template <class T>
|
||||
void VariantAssign(const T& rhs, double)
|
||||
{
|
||||
Private::SafeAssign(*this, rhs);
|
||||
}
|
||||
|
||||
// Assignment from another Variant instantiation
|
||||
template <class TList2, typename Align2>
|
||||
void VariantAssign(const Variant<TList2, Align2>& rhs, int)
|
||||
{
|
||||
Private::SafeAssign(*this, rhs);
|
||||
}
|
||||
|
||||
public:
|
||||
// VC7 don't support partial ordering
|
||||
template <class T>
|
||||
Variant& operator=(const T& rhs)
|
||||
{
|
||||
// Both VariantAssign are the same in this implementation
|
||||
VariantAssign(rhs, int(0));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ~
|
||||
~Variant()
|
||||
{
|
||||
(vptr_->destroy_)(*this);
|
||||
}
|
||||
|
||||
// Visitors definitions
|
||||
// @@@ Possible improvement: add defintions of visitor who return
|
||||
// something else than void
|
||||
|
||||
typedef ::Loki::Visitor<TList, void> StrictVisitor;
|
||||
typedef ::Loki::Visitor<typename MakeConst<TList>::Result, void>
|
||||
ConstStrictVisitor;
|
||||
typedef ::Loki::NonStrictVisitor<TList, void> NonStrictVisitor;
|
||||
typedef ::Loki::NonStrictVisitor<typename MakeConst<TList>::Result, void>
|
||||
ConstNonStrictVisitor;
|
||||
|
||||
private:
|
||||
// VTable structure
|
||||
// The essential component of the fake vtable idiom, VTable contains
|
||||
// pointers to functions, pointers that will be filled up with addresses
|
||||
// of functions in VTableImpl
|
||||
|
||||
struct VTable
|
||||
{
|
||||
const std::type_info& (*typeId_)();
|
||||
void (*destroy_)(const Variant&);
|
||||
void (*clone_)(const Variant&, Variant&);
|
||||
void (*swap_)(void* lhs, void* rhs);
|
||||
void (*accept_)(Variant&, StrictVisitor&);
|
||||
void (*acceptConst_)(const Variant&, ConstStrictVisitor&);
|
||||
};
|
||||
|
||||
// VTable concrete implementations
|
||||
// VTableImpl<T> contains definitions for all of a VTable's pointer to
|
||||
// functions.
|
||||
|
||||
// VC7 thinks that Variant inside VTableImpl is template
|
||||
typedef Variant VariantType;
|
||||
|
||||
template <class T>
|
||||
struct VTableImpl
|
||||
{
|
||||
private:
|
||||
static const std::type_info& TypeId()
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
static void Destroy(const VariantType& var)
|
||||
{
|
||||
const T& data = *reinterpret_cast<const T*>(&var.buffer_[0]);
|
||||
(void)data.~T();
|
||||
}
|
||||
|
||||
static void Swap(void* lhs, void* rhs)
|
||||
{
|
||||
Private::SwapHelper(*static_cast<T*>(lhs), *static_cast<T*>(rhs));
|
||||
}
|
||||
|
||||
static void Clone(const VariantType& src, VariantType& dest)
|
||||
{
|
||||
new(&dest.buffer_[0]) T(
|
||||
*reinterpret_cast<const T*>(&src.buffer_[0]));
|
||||
dest.vptr_ = src.vptr_;
|
||||
}
|
||||
|
||||
static void Accept(VariantType& var, StrictVisitor& visitor)
|
||||
{
|
||||
typedef typename StrictVisitor::ReturnType RType;
|
||||
::Loki::Visitor<T,RType> &v = visitor;
|
||||
|
||||
v.Visit(*reinterpret_cast<T*>(&var.buffer_[0]));
|
||||
}
|
||||
|
||||
static void AcceptConst(const VariantType& var, ConstStrictVisitor& visitor)
|
||||
{
|
||||
typedef typename ConstStrictVisitor::ReturnType RType;
|
||||
::Loki::Visitor<const T,RType> &v = visitor;
|
||||
|
||||
v.Visit(*reinterpret_cast<const T*>(&var.buffer_[0]));
|
||||
}
|
||||
|
||||
public:
|
||||
static const VTable *GetVPTR()
|
||||
{
|
||||
static const VTable vTbl_ =
|
||||
{
|
||||
&TypeId,
|
||||
&Destroy,
|
||||
&Clone,
|
||||
&Swap,
|
||||
&Accept,
|
||||
&AcceptConst,
|
||||
};
|
||||
|
||||
return &vTbl_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> friend struct VTableImpl;
|
||||
|
||||
private: // should be private; some compilers prefer 'public' :o}
|
||||
|
||||
enum { neededSize = MaxSize<TList>::result };
|
||||
|
||||
VTable const * vptr_;
|
||||
union
|
||||
{
|
||||
Align dummy_;
|
||||
char buffer_[neededSize];
|
||||
};
|
||||
|
||||
public:
|
||||
void swap(Variant& rhs)
|
||||
{
|
||||
if (this->TypeId() == rhs.TypeId())
|
||||
{
|
||||
(vptr_->swap_)(this->buffer_, rhs.buffer_);
|
||||
}
|
||||
else
|
||||
{
|
||||
Private::SafeSwap(*this, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
const std::type_info& TypeId() const
|
||||
{
|
||||
return (vptr_->typeId_)();
|
||||
}
|
||||
|
||||
template <typename T> T* GetPtr()
|
||||
{
|
||||
return TypeId() == typeid(T)
|
||||
? reinterpret_cast<T*>(&buffer_[0])
|
||||
: 0;
|
||||
}
|
||||
|
||||
template <typename T> const T* GetPtr() const
|
||||
{
|
||||
return TypeId() == typeid(T)
|
||||
? reinterpret_cast<const T*>(&buffer_[0])
|
||||
: 0;
|
||||
}
|
||||
|
||||
template <typename T> T& Get()
|
||||
{
|
||||
T* p = GetPtr<T>();
|
||||
if (!p) throw std::runtime_error("Variant::Get() Invalid variant type");
|
||||
return *p;
|
||||
}
|
||||
|
||||
template <typename T> const T& Get() const
|
||||
{
|
||||
const T* p = GetPtr<T>();
|
||||
if (!p) throw std::runtime_error("Variant::Get() const Invalid variant type");
|
||||
return *p;
|
||||
}
|
||||
|
||||
// Visitation primitives
|
||||
// Although there are four visitor types, only two Accept functions are
|
||||
// necessary, because the non-strict visitors inherit the strict visitors
|
||||
|
||||
void Accept(StrictVisitor& visitor)
|
||||
{
|
||||
(vptr_->accept_)(*this, visitor);
|
||||
}
|
||||
|
||||
void Accept(ConstStrictVisitor& visitor) const
|
||||
{
|
||||
(vptr_->acceptConst_)(*this, visitor);
|
||||
}
|
||||
|
||||
// Extracts the value of a Variant converted to a specific type
|
||||
|
||||
template <class To> To ConvertTo() const
|
||||
{
|
||||
typename ConverterTo<Variant, To>::Visitor v;
|
||||
ConstStrictVisitor& visitor = v;
|
||||
this->Accept(visitor);
|
||||
return v.GetDestination();
|
||||
}
|
||||
|
||||
// Changes the type of a Variant in-place
|
||||
|
||||
template <class To> void ChangeType()
|
||||
{
|
||||
Variant(this->ConvertTo<To>()).swap(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// July 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
328
include/noncc/MSVC/1300/Visitor.h
Executable file
328
include/noncc/MSVC/1300/Visitor.h
Executable 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_
|
||||
|
2
include/noncc/MSVC/1300/portby.txt
Executable file
2
include/noncc/MSVC/1300/portby.txt
Executable file
|
@ -0,0 +1,2 @@
|
|||
MSVC7
|
||||
Rani Sharoni
|
18
include/noncc/MSVC/1300/readme.txt
Executable file
18
include/noncc/MSVC/1300/readme.txt
Executable 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
|
57
include/noncc/MSVC/1300/static_check.h
Executable file
57
include/noncc/MSVC/1300/static_check.h
Executable file
|
@ -0,0 +1,57 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef STATIC_CHECK_INC_
|
||||
#define STATIC_CHECK_INC_
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper structure for the STATIC_CHECK macro
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool CompileTimeAssertion>
|
||||
struct CompileTimeError;
|
||||
|
||||
template<>
|
||||
struct CompileTimeError<true>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// macro STATIC_CHECK
|
||||
// Invocation: STATIC_CHECK(expr, id)
|
||||
// where:
|
||||
// expr is a compile-time integral or pointer expression
|
||||
// id is a C++ identifier that does not need to be defined
|
||||
// If expr is zero, id will appear in a compile-time error message.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define STATIC_CHECK(expr, msg) \
|
||||
typedef char ERROR_##msg[1][(expr)]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun
|
||||
// definition
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// July 09, 2002: improved for favor of VC diagnostic and usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // STATIC_CHECK_INC_
|
Loading…
Add table
Add a link
Reference in a new issue