From ca94249f9456ab84957ad72413bda0ebcbdde194 Mon Sep 17 00:00:00 2001 From: tslettebo Date: Mon, 6 Jan 2003 02:26:33 +0000 Subject: [PATCH] Benjamin Kaufmann's port git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@86 7ec92016-0320-0410-acc4-a06ded1c099a --- MSVC/1200/AbstractFactory.h | 217 ++++ MSVC/1200/AssocVector.h | 335 +++++ MSVC/1200/EmptyType.h | 37 + MSVC/1200/Factory.h | 146 +++ MSVC/1200/Functor.h | 2054 +++++++++++++++++++++++++++++++ MSVC/1200/HierarchyGenerators.h | 460 +++++++ MSVC/1200/MSVC6Helpers.h | 157 +++ MSVC/1200/MultiMethods.h | 466 +++++++ MSVC/1200/NullType.h | 37 + MSVC/1200/Readme.txt | 239 ++++ MSVC/1200/Singleton.cpp | 49 + MSVC/1200/Singleton.h | 480 ++++++++ MSVC/1200/SmallObj.cpp | 420 +++++++ MSVC/1200/SmallObj.h | 193 +++ MSVC/1200/SmartPtr.h | 1447 ++++++++++++++++++++++ MSVC/1200/Threads.h | 219 ++++ MSVC/1200/Tuple.h | 22 + MSVC/1200/TypeInfo.h | 106 ++ MSVC/1200/TypeManip.h | 268 ++++ MSVC/1200/TypeTraits.h | 302 +++++ MSVC/1200/Typelist.h | 1146 +++++++++++++++++ MSVC/1200/Visitor.h | 556 +++++++++ MSVC/1200/static_check.h | 63 + 23 files changed, 9419 insertions(+) create mode 100644 MSVC/1200/AbstractFactory.h create mode 100644 MSVC/1200/AssocVector.h create mode 100644 MSVC/1200/EmptyType.h create mode 100644 MSVC/1200/Factory.h create mode 100644 MSVC/1200/Functor.h create mode 100644 MSVC/1200/HierarchyGenerators.h create mode 100644 MSVC/1200/MSVC6Helpers.h create mode 100644 MSVC/1200/MultiMethods.h create mode 100644 MSVC/1200/NullType.h create mode 100644 MSVC/1200/Readme.txt create mode 100644 MSVC/1200/Singleton.cpp create mode 100644 MSVC/1200/Singleton.h create mode 100644 MSVC/1200/SmallObj.cpp create mode 100644 MSVC/1200/SmallObj.h create mode 100644 MSVC/1200/SmartPtr.h create mode 100644 MSVC/1200/Threads.h create mode 100644 MSVC/1200/Tuple.h create mode 100644 MSVC/1200/TypeInfo.h create mode 100644 MSVC/1200/TypeManip.h create mode 100644 MSVC/1200/TypeTraits.h create mode 100644 MSVC/1200/Typelist.h create mode 100644 MSVC/1200/Visitor.h create mode 100644 MSVC/1200/static_check.h diff --git a/MSVC/1200/AbstractFactory.h b/MSVC/1200/AbstractFactory.h new file mode 100644 index 0000000..453b611 --- /dev/null +++ b/MSVC/1200/AbstractFactory.h @@ -0,0 +1,217 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 24, 2002 +// 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 + +#define ETAS_HELPER(Type) ((Type*)0) + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template AbstractFactoryUnit +// The building block of an Abstract Factory +//////////////////////////////////////////////////////////////////////////////// + + template + class AbstractFactoryUnit + { + public: + virtual T* DoCreate(Type2Type) = 0; + virtual ~AbstractFactoryUnit() {} + }; + + // Wrapper for AbstractFactoryUnit. + struct AbstractFactoryUnitWrapper + { + template + struct In + { + typedef AbstractFactoryUnit 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 T* whose sole +// responsibility is to help the compiler in deducing the type of T. +// Using this port the call: +// ConcProduct* p = aFactory.Create(); +// therefore becomes: +// ConcProduct* p = aFactory.Create((ConcProduct*)0); + + template + < + class TList, + class Unit = AbstractFactoryUnitWrapper + > + class AbstractFactory : public GenScatterHierarchy + { + public: + typedef TList ProductList; + + template T* Create(T* DeduceHelper) + { + ApplyInnerType::type& unit = *this; + return unit.DoCreate(Type2Type()); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template OpNewFactoryUnit +// Creates an object by invoking the new operator +//////////////////////////////////////////////////////////////////////////////// + + template + 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) + { + return new ConcreteProduct; + } + }; + + // Wrapper for OpNewFactoryUnit + struct OpNewFactoryUnitWrapper + { + template + struct In + { + typedef OpNewFactoryUnit 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 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 + void GetPrototype(AbstractProduct*& p) + { return DoGetPrototype(*this, p); } + + template + void SetPrototype(U* pObj) + { DoSetPrototype(*this, pObj); } + + AbstractProduct* DoCreate(Type2Type) + { + 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(pPrototype_->Clone()); + } + + private: + AbstractProduct* pPrototype_; + }; + + // Wrapper for PrototypeFactoryUnit + struct PrototypeFactoryUnitWrapper + { + template + struct In + { + typedef PrototypeFactoryUnit 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::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 +//////////////////////////////////////////////////////////////////////////////// + +#endif // ABSTRACTFACTORY_INC_ diff --git a/MSVC/1200/AssocVector.h b/MSVC/1200/AssocVector.h new file mode 100644 index 0000000..2b4386e --- /dev/null +++ b/MSVC/1200/AssocVector.h @@ -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 +#include +#include +#include + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template AssocVectorCompare +// Used by AssocVector +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + class AssocVectorCompare : public C + { + typedef std::pair + 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 not std::pair +// * iterators are random +//////////////////////////////////////////////////////////////////////////////// + + template + < + class K, + class V, + class C = std::less, + class A = std::allocator< std::pair > + > + class AssocVector + : private std::vector< std::pair, A > + , private Private::AssocVectorCompare + { + typedef std::vector, A> Base; + typedef Private::AssocVectorCompare 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 + , 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 + 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 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 + 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 equal_range(const key_type& k) + { + MyCompare& me = *this; + return std::equal_range(begin(), end(), k, me); + } + + std::pair 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 + void swap(AssocVector& lhs, AssocVector& 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_ diff --git a/MSVC/1200/EmptyType.h b/MSVC/1200/EmptyType.h new file mode 100644 index 0000000..5227ba8 --- /dev/null +++ b/MSVC/1200/EmptyType.h @@ -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_ diff --git a/MSVC/1200/Factory.h b/MSVC/1200/Factory.h new file mode 100644 index 0000000..0d0376e --- /dev/null +++ b/MSVC/1200/Factory.h @@ -0,0 +1,146 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 24, 2002 + +#ifndef FACTORY_INC_ +#define FACTORY_INC_ + +#include "TypeInfo.h" +#include "AssocVector.h" +#include + +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 + static AbstractProduct* OnUnknownType(IdentifierType) + { + throw Exception(); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Factory +// Implements a generic object factory +//////////////////////////////////////////////////////////////////////////////// + + template + < + class AbstractProduct, + typename IdentifierType, + typename ProductCreator = AbstractProduct* (*)(), + class FactoryErrorPolicy = DefaultFactoryError + > + class Factory + : public FactoryErrorPolicy + { + public: + bool Register(const IdentifierType& id, ProductCreator creator) + { + return associations_.insert( + IdToProductMap::value_type(id, creator)).second; + } + + bool Unregister(const IdentifierType& id) + { + return associations_.erase(id) == 1; + } + + AbstractProduct* CreateObject(const IdentifierType& id) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + { + return (i->second)(); + } + return OnUnknownType(id); + } + + private: + typedef AssocVector 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)),(AbstractProduct*)0); + } + + private: + typedef AssocVector 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. +//////////////////////////////////////////////////////////////////////////////// + +#endif // FACTORY_INC_ diff --git a/MSVC/1200/Functor.h b/MSVC/1200/Functor.h new file mode 100644 index 0000000..3a221ad --- /dev/null +++ b/MSVC/1200/Functor.h @@ -0,0 +1,2054 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 14, 2002 +// All functors will return an object of the udt VoidAsType if the template +// parameter R is void. +// *Do not* use this returned object. It is only used as a workaround. + +#ifndef FUNCTOR_INC_ +#define FUNCTOR_INC_ + +#include "Typelist.h" +#include "EmptyType.h" +#include "SmallObj.h" +#include "TypeTraits.h" +#include +#include +#include "MSVC6Helpers.h" +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl (internal) +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + struct FunctorImplBase : public SmallObject + { + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef EmptyType Parm1; + typedef EmptyType Parm2; + typedef EmptyType Parm3; + typedef EmptyType Parm4; + typedef EmptyType Parm5; + typedef EmptyType Parm6; + typedef EmptyType Parm7; + typedef EmptyType Parm8; + typedef EmptyType Parm9; + typedef EmptyType Parm10; + typedef EmptyType Parm11; + typedef EmptyType Parm12; + typedef EmptyType Parm13; + typedef EmptyType Parm14; + typedef EmptyType Parm15; + + virtual FunctorImplBase* DoClone() const = 0; + template + static U* Clone(U* pObj) + { + if (!pObj) return 0; + U* pClone = static_cast(pObj->DoClone()); + assert(typeid(*pClone) == typeid(*pObj)); + return pClone; + } + virtual ~FunctorImplBase () {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// macro DEFINE_CLONE_FUNCTORIMPL +// Implements the DoClone function for a functor implementation +//////////////////////////////////////////////////////////////////////////////// + +#define DEFINE_CLONE_FUNCTORIMPL(Cls) \ + virtual Private::FunctorImplBase* \ + DoClone() const { return new Cls(*this); } + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Base template +//////////////////////////////////////////////////////////////////////////////// + template + struct FunctorImplHelper; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 0 (zero) parameters +//////////////////////////////////////////////////////////////////////////////// + + template <> + struct FunctorImplHelper<0> + { + template + class In : public Private::FunctorImplBase + { + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + virtual NewRType operator()() = 0; + }; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 1 parameter +//////////////////////////////////////////////////////////////////////////////// + + template <> + struct FunctorImplHelper<1> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + virtual NewRType operator()(Parm1) = 0; + }; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 2 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<2> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + virtual NewRType operator()(Parm1, Parm2) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 3 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<3> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + virtual NewRType operator()(Parm1, Parm2, Parm3) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 4 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<4> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 5 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<5> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 6 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<6> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 7 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<7> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 8 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<8> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 9 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<9> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 10 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<10> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 11 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<11> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + typedef typename TL::TypeAt::Result P11; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + typedef typename TypeTraits::ParameterType Parm11; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10, Parm11) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 12 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<12> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + typedef typename TL::TypeAt::Result P11; + typedef typename TL::TypeAt::Result P12; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + typedef typename TypeTraits::ParameterType Parm11; + typedef typename TypeTraits::ParameterType Parm12; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 13 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<13> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + typedef typename TL::TypeAt::Result P11; + typedef typename TL::TypeAt::Result P12; + typedef typename TL::TypeAt::Result P13; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + typedef typename TypeTraits::ParameterType Parm11; + typedef typename TypeTraits::ParameterType Parm12; + typedef typename TypeTraits::ParameterType Parm13; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 14 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<14> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + typedef typename TL::TypeAt::Result P11; + typedef typename TL::TypeAt::Result P12; + typedef typename TL::TypeAt::Result P13; + typedef typename TL::TypeAt::Result P14; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + typedef typename TypeTraits::ParameterType Parm11; + typedef typename TypeTraits::ParameterType Parm12; + typedef typename TypeTraits::ParameterType Parm13; + typedef typename TypeTraits::ParameterType Parm14; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 15 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<15> + { + template + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + typedef typename TL::TypeAt::Result P3; + typedef typename TL::TypeAt::Result P4; + typedef typename TL::TypeAt::Result P5; + typedef typename TL::TypeAt::Result P6; + typedef typename TL::TypeAt::Result P7; + typedef typename TL::TypeAt::Result P8; + typedef typename TL::TypeAt::Result P9; + typedef typename TL::TypeAt::Result P10; + typedef typename TL::TypeAt::Result P11; + typedef typename TL::TypeAt::Result P12; + typedef typename TL::TypeAt::Result P13; + typedef typename TL::TypeAt::Result P14; + typedef typename TL::TypeAt::Result P15; + + public: + typedef R ResultType; + typedef typename Select + < + IsVoid::value != 0, + VoidAsType, + R + >::Result NewRType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + typedef typename TypeTraits::ParameterType Parm6; + typedef typename TypeTraits::ParameterType Parm7; + typedef typename TypeTraits::ParameterType Parm8; + typedef typename TypeTraits::ParameterType Parm9; + typedef typename TypeTraits::ParameterType Parm10; + typedef typename TypeTraits::ParameterType Parm11; + typedef typename TypeTraits::ParameterType Parm12; + typedef typename TypeTraits::ParameterType Parm13; + typedef typename TypeTraits::ParameterType Parm14; + typedef typename TypeTraits::ParameterType Parm15; + virtual NewRType operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14, Parm15) = 0; + }; + }; + + } // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// The base class for a hierarchy of functors. The FunctorImpl class is not used +// directly; rather, the Functor class manages and forwards to a pointer to +// FunctorImpl +// You may want to derive your own functors from FunctorImpl. +// Specializations of FunctorImpl for up to 15 parameters follow +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename R, + class TList, + class ThreadingModel = DEFAULT_THREADING + > + class FunctorImpl + : public Private::FunctorImplHelper + < + TL::Length::value + > + ::template In + { + ASSERT_TYPELIST(TList); + public: + virtual ~FunctorImpl() {} + }; + +//////////////////////////////////////////////////////////////////////////////// +namespace Private +{ + template + struct FunCallWrapper + { + template + struct In + { + typedef typename ParentFunctor::Impl Base; + typedef typename Base::Parm1 A0; + typedef typename Base::Parm2 A1; + typedef typename Base::Parm3 A2; + typedef typename Base::Parm4 A3; + typedef typename Base::Parm5 A4; + typedef typename Base::Parm6 A5; + typedef typename Base::Parm7 A6; + typedef typename Base::Parm8 A7; + typedef typename Base::Parm9 A8; + typedef typename Base::Parm10 A9; + typedef typename Base::Parm11 A10; + typedef typename Base::Parm12 A11; + typedef typename Base::Parm13 A12; + typedef typename Base::Parm14 A13; + typedef typename Base::Parm15 A14; + private: + Fun f_; + public: + In(Fun f) : f_(f) {} + + + R operator() (){return f_();} + R operator()(A0 p0) {return f_(p0);} + R operator()(A0 p0, A1 p1) {return f_(p0, p1);} + + + R operator()(A0 p0, A1 p1, A2 p2) + {return f_(p0, p1, p2);} + + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3) + {return f_(p0, p1, p2, p3);} + + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4) + {return f_(p0, p1, p2, p3, p4);} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5) + {return f_(p0, p1, p2, p3, p4, p5);} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6) + {return f_(p0, p1, p2, p3, p4, p5, p6);} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7) + {return f_(p0, p1, p2, p3, p4, p5, p6, p7);} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8) + {return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8);} + + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9) + {return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10) + {return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11) + {return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12) + { + return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13) + { + return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13, A14 p14) + { + return f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13, p14); + } + + }; + }; + + template <> + struct FunCallWrapper + { + template + struct In + { + typedef typename ParentFunctor::Impl Base; + typedef typename Base::Parm1 A0; + typedef typename Base::Parm2 A1; + typedef typename Base::Parm3 A2; + typedef typename Base::Parm4 A3; + typedef typename Base::Parm5 A4; + typedef typename Base::Parm6 A5; + typedef typename Base::Parm7 A6; + typedef typename Base::Parm8 A7; + typedef typename Base::Parm9 A8; + typedef typename Base::Parm10 A9; + typedef typename Base::Parm11 A10; + typedef typename Base::Parm12 A11; + typedef typename Base::Parm13 A12; + typedef typename Base::Parm14 A13; + typedef typename Base::Parm15 A14; + typedef VoidAsType R; + private: + Fun f_; + public: + In(Fun f) : f_(f) {} + + R operator() (){f_(); return VoidAsType();} + R operator()(A0 p0) {f_(p0); return VoidAsType();} + R operator()(A0 p0, A1 p1) {f_(p0, p1); return VoidAsType();} + R operator()(A0 p0, A1 p1, A2 p2) + {f_(p0, p1, p2); return VoidAsType();} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3) + {f_(p0, p1, p2, p3); return VoidAsType();} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4) + {f_(p0, p1, p2, p3, p4); return VoidAsType();} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5) + {f_(p0, p1, p2, p3, p4, p5); return VoidAsType();} + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6) + {f_(p0, p1, p2, p3, p4, p5, p6); return VoidAsType();} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7) + {f_(p0, p1, p2, p3, p4, p5, p6, p7); return VoidAsType();} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8) + {f_(p0, p1, p2, p3, p4, p5, p6, p7, p8); return VoidAsType();} + + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9) + {f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); return VoidAsType();} + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10) + { + f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11) + { + f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12) + { + f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13) + { + f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, + p13); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13, A14 p14) + { + f_(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, + p13, p14); + return VoidAsType(); + } + }; + }; + + template + struct MemFunCallWrapper + { + template + struct In + { + typedef typename ParentFunctor::Impl Base; + typedef typename Base::Parm1 A0; + typedef typename Base::Parm2 A1; + typedef typename Base::Parm3 A2; + typedef typename Base::Parm4 A3; + typedef typename Base::Parm5 A4; + typedef typename Base::Parm6 A5; + typedef typename Base::Parm7 A6; + typedef typename Base::Parm8 A7; + typedef typename Base::Parm9 A8; + typedef typename Base::Parm10 A9; + typedef typename Base::Parm11 A10; + typedef typename Base::Parm12 A11; + typedef typename Base::Parm13 A12; + typedef typename Base::Parm14 A13; + typedef typename Base::Parm15 A14; + private: + pToObj pObj_; + pToMemFun pMemFun_; + public: + In(const pToObj& pObj, pToMemFun pMemFun) + : pObj_(pObj) + , pMemFun_(pMemFun) + {} + + R operator() (){return ((*pObj_).*pMemFun_)();} + R operator()(A0 p0) {return ((*pObj_).*pMemFun_)(p0);} + R operator()(A0 p0, A1 p1) + { + return ((*pObj_).*pMemFun_)(p0, p1); + } + + + R operator()(A0 p0, A1 p1, A2 p2) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8); + } + + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12, p13); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13, A14 p14) + { + return ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12, p13, p14); + } + + }; + }; + + template <> + struct MemFunCallWrapper + { + template + struct In + { + typedef VoidAsType R; + typedef typename ParentFunctor::Impl Base; + typedef typename Base::Parm1 A0; + typedef typename Base::Parm2 A1; + typedef typename Base::Parm3 A2; + typedef typename Base::Parm4 A3; + typedef typename Base::Parm5 A4; + typedef typename Base::Parm6 A5; + typedef typename Base::Parm7 A6; + typedef typename Base::Parm8 A7; + typedef typename Base::Parm9 A8; + typedef typename Base::Parm10 A9; + typedef typename Base::Parm11 A10; + typedef typename Base::Parm12 A11; + typedef typename Base::Parm13 A12; + typedef typename Base::Parm14 A13; + typedef typename Base::Parm15 A14; + private: + pToObj pObj_; + pToMemFun pMemFun_; + public: + In(const pToObj& pObj, pToMemFun pMemFun) + : pObj_(pObj) + , pMemFun_(pMemFun) + {} + + R operator() (){((*pObj_).*pMemFun_)(); return VoidAsType();} + R operator()(A0 p0) + {((*pObj_).*pMemFun_)(p0); return VoidAsType();} + R operator()(A0 p0, A1 p1) + { + ((*pObj_).*pMemFun_)(p0, p1); + return VoidAsType(); + } + + + R operator()(A0 p0, A1 p1, A2 p2) + { + ((*pObj_).*pMemFun_)(p0, p1, p2); + return VoidAsType(); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3); + return VoidAsType(); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4); + return VoidAsType(); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5); + return VoidAsType(); + } + + R operator()(A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8); + return VoidAsType(); + } + + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12, p13); + return VoidAsType(); + } + + R operator()( A0 p0, A1 p1, A2 p2, A3 p3, A4 p4, A5 p5, A6 p6, + A7 p7, A8 p8, A9 p9, A10 p10, A11 p11, A12 p12, + A13 p13, A14 p14) + { + ((*pObj_).*pMemFun_)(p0, p1, p2, p3, p4, p5, p6, + p7, p8, p9, p10, p11, p12, p13, p14); + return VoidAsType(); + } + + }; + }; + +} + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorHandler +// Wraps functors and pointers to functions +//////////////////////////////////////////////////////////////////////////////// + template + class FunctorHandler : public ParentFunctor::Impl + { + typedef typename ParentFunctor::Impl Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::NewRType NewRType; + typedef typename ParentFunctor::ThreadModel ThreadModel; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + private: + typedef typename + Private::FunCallWrapper::template In + CallImplType; + public: + FunctorHandler(const Fun& fun) : CallImpl_(fun) {} + + DEFINE_CLONE_FUNCTORIMPL(FunctorHandler) + + // operator() implementations for up to 15 arguments + + NewRType operator()() + { + return CallImpl_(); + } + + NewRType operator()(Parm1 p1) + { return CallImpl_(p1);} + + NewRType operator()(Parm1 p1, Parm2 p2) + { return CallImpl_(p1, p2); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return CallImpl_(p1, p2, p3); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return CallImpl_(p1, p2, p3, p4);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return CallImpl_(p1, p2, p3, p4, p5);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return CallImpl_(p1, p2, p3, p4, p5, p6);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14);} + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15);} + + private: + CallImplType CallImpl_; + }; + + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorHandler +// Wraps pointers to member functions +//////////////////////////////////////////////////////////////////////////////// + + template + class MemFunHandler : public ParentFunctor::Impl + { + typedef typename ParentFunctor::Impl Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::NewRType NewRType; + typedef typename ParentFunctor::ThreadModel ThreadModel; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + private: + typedef typename Private::MemFunCallWrapper::template In + < + ParentFunctor, + PointerToObj, + PointerToMemFn + > CallImplType; + + public: + MemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn) + : CallImpl_(pObj, pMemFn) + {} + + DEFINE_CLONE_FUNCTORIMPL(MemFunHandler) + + NewRType operator()() + { return CallImpl_(); } + + NewRType operator()(Parm1 p1) + { return CallImpl_(p1); } + + NewRType operator()(Parm1 p1, Parm2 p2) + { return CallImpl_(p1, p2); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return CallImpl_(p1, p2, p3); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return CallImpl_(p1, p2, p3, p4); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return CallImpl_(p1, p2, p3, p4, p5); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return CallImpl_(p1, p2, p3, p4, p5, p6); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { + return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { + return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { + return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return CallImpl_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15); + } + + private: + CallImplType CallImpl_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Functor +// A generalized functor implementation with value semantics +//////////////////////////////////////////////////////////////////////////////// + + template + class Functor + { + public: + // Handy type definitions for the body type + typedef FunctorImpl Impl; + typedef R ResultType; + typedef TList ParmList; + typedef ThreadingModel ThreadModel; + typedef typename Select + < Private::IsVoid::value != 0, + Private::VoidAsType, R + >::Result NewRType; + + typedef typename Impl::Parm1 Parm1; + typedef typename Impl::Parm2 Parm2; + typedef typename Impl::Parm3 Parm3; + typedef typename Impl::Parm4 Parm4; + typedef typename Impl::Parm5 Parm5; + typedef typename Impl::Parm6 Parm6; + typedef typename Impl::Parm7 Parm7; + typedef typename Impl::Parm8 Parm8; + typedef typename Impl::Parm9 Parm9; + typedef typename Impl::Parm10 Parm10; + typedef typename Impl::Parm11 Parm11; + typedef typename Impl::Parm12 Parm12; + typedef typename Impl::Parm13 Parm13; + typedef typename Impl::Parm14 Parm14; + typedef typename Impl::Parm15 Parm15; + public: + // Member functions + Functor() : spImpl_() + {} + + + // Copy-Ctor. + Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())) + {} + + + // Ctor for user defined impl-classes + Functor(std::auto_ptr spImpl) : spImpl_(spImpl) + {} + + // we can't use loki's original approach with VC 6 because + // this compiler will not recognize the copy-ctor + // if a template-ctor is present. + // template + // Functor(Fun fun) + // : spImpl_(new FunctorHandler(fun)) + // {} + + // dummy-Parameter added. + template + Functor(Fun fun, int* pDummy) + : spImpl_(new FunctorHandler(fun)) + {} + + // ctors for functions with up to 15 arguments. + template + Functor(R (*p)()) : spImpl_(new FunctorHandler(p)) + {} + + template + Functor(R (*p)(A0)) + : spImpl_(new FunctorHandler(p)) + {} + + template + Functor(R (*p)(A0, A1)) + : spImpl_(new FunctorHandler(p)) + {} + + template + Functor(R (*p)(A0, A1, A2)) + : spImpl_(new FunctorHandler(p)) + {} + + template + Functor(R (*p)(A0, A1, A2, A3)) + : spImpl_(new FunctorHandler(p)) + {} + + template + Functor(R (*p)(A0, A1, A2, A3, A4)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)) + : spImpl_(new FunctorHandler(p)) + {} + + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9, class A10 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9, class A10, + class A11 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9, class A10, + class A11, class A12 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9, class A10, + class A11, class A12, class A13 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) + : spImpl_(new FunctorHandler(p)) + {} + + template + < + class R, class A0, class A1, class A2, class A3, class A4, + class A5, class A6, class A7, class A8, class A9, class A10, + class A11, class A12, class A13, class A14 + > + Functor(R (*p)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) + : spImpl_(new FunctorHandler(p)) + {} + + + template + Functor(const PtrObj& p, MemFn memFn) + : spImpl_(new MemFunHandler(p, memFn)) + {} + + Functor& operator=(const Functor& rhs) + { + if (this == &rhs) + return *this; + // the auto_ptr provided by the MSVC 6.0 does not have + // a reset-function. + Functor copy(rhs); + delete spImpl_.release(); + spImpl_ = copy.spImpl_; + + return *this; + } + + NewRType operator()() + { return (*spImpl_)(); } + + NewRType operator()(Parm1 p1) + { return (*spImpl_)(p1); } + + NewRType operator()(Parm1 p1, Parm2 p2) + { return (*spImpl_)(p1, p2); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return (*spImpl_)(p1, p2, p3); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return (*spImpl_)(p1, p2, p3, p4); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return (*spImpl_)(p1, p2, p3, p4, p5); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13, p14); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13, p14, p15); + } + + private: + std::auto_ptr spImpl_; + + }; + + namespace Private + { + template + struct BinderFirstTraits + { + private: + typedef typename Fctor::ParmList TList; + + public: + typedef typename TL::Erase + < + TList, + typename TL::TypeAt::Result + > + ::Result ParmList; + typedef typename Fctor::ThreadModel ThreadModel; + //typedef typename TList::Tail ParmList; + + typedef Functor BoundFunctorType; + typedef typename BoundFunctorType::Impl Impl; + }; + + } // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template BinderFirst +// Binds the first parameter of a Functor object to a specific value +//////////////////////////////////////////////////////////////////////////////// + + template + class BinderFirst + : public Private::BinderFirstTraits::Impl + { + typedef typename Private::BinderFirstTraits::Impl Base; + typedef typename Private::BinderFirstTraits::ThreadModel ThreadModel; + typedef typename OriginalFunctor::ResultType ResultType; + typedef typename Select + < Private::IsVoid::value != 0, + Private::VoidAsType, ResultType + >::Result NewRType; + typedef typename OriginalFunctor::Parm1 BoundType; + + typedef typename OriginalFunctor::Parm2 Parm1; + typedef typename OriginalFunctor::Parm3 Parm2; + typedef typename OriginalFunctor::Parm4 Parm3; + typedef typename OriginalFunctor::Parm5 Parm4; + typedef typename OriginalFunctor::Parm6 Parm5; + typedef typename OriginalFunctor::Parm7 Parm6; + typedef typename OriginalFunctor::Parm8 Parm7; + typedef typename OriginalFunctor::Parm9 Parm8; + typedef typename OriginalFunctor::Parm10 Parm9; + typedef typename OriginalFunctor::Parm11 Parm10; + typedef typename OriginalFunctor::Parm12 Parm11; + typedef typename OriginalFunctor::Parm13 Parm12; + typedef typename OriginalFunctor::Parm14 Parm13; + typedef typename OriginalFunctor::Parm15 Parm14; + typedef EmptyType Parm15; + public: + BinderFirst(const OriginalFunctor& fun, BoundType bound) + : f_(fun), b_(bound) + {} + + DEFINE_CLONE_FUNCTORIMPL(BinderFirst) + + // operator() implementations for up to 15 arguments + + NewRType operator()() + { return f_(b_); } + + NewRType operator()(Parm1 p1) + { return f_(b_, p1); } + + NewRType operator()(Parm1 p1, Parm2 p2) + { return f_(b_, p1, p2); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f_(b_, p1, p2, p3); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f_(b_, p1, p2, p3, p4); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f_(b_, p1, p2, p3, p4, p5); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f_(b_, p1, p2, p3, p4, p5, p6); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + // VC7 BUG + virtual ~BinderFirst() {} + private: + OriginalFunctor f_; + BoundType b_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template BindFirst +// Binds the first parameter of a Functor object to a specific value +//////////////////////////////////////////////////////////////////////////////// + + template + typename Private::BinderFirstTraits::BoundFunctorType + BindFirst( + const Fctor& fun, + typename Fctor::Parm1 bound) + { + typedef typename Private::BinderFirstTraits::BoundFunctorType + Outgoing; + typedef typename Private::BinderFirstTraits::BoundFunctorType::Impl + Impl; + return Outgoing(std::auto_ptr( + new BinderFirst(fun, bound))); + } + +//////////////////////////////////////////////////////////////////////////////// +// class template Chainer +// Chains two functor calls one after another +//////////////////////////////////////////////////////////////////////////////// + + template + class Chainer : public Fun2::Impl + { + typedef Fun2 Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::ThreadModel ThreadModel; + typedef typename Select + < Private::IsVoid::value != 0, + Private::VoidAsType, ResultType + >::Result NewRType; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + + Chainer(const Fun1& fun1, const Fun2& fun2) : f1_(fun1), f2_(fun2) {} + + // + // VC7 don't see this implicit constructor + // + + virtual ~Chainer() {} + + DEFINE_CLONE_FUNCTORIMPL(Chainer) + + // operator() implementations for up to 15 arguments + + NewRType operator()() + { return f1_(), f2_(); } + + NewRType operator()(Parm1 p1) + { return f1_(p1), f2_(p1); } + + NewRType operator()(Parm1 p1, Parm2 p2) + { return f1_(p1, p2), f2_(p1, p2); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f1_(p1, p2, p3), f2_(p1, p2, p3); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f1_(p1, p2, p3, p4), f2_(p1, p2, p3, p4); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f1_(p1, p2, p3, p4, p5), f2_(p1, p2, p3, p4, p5); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f1_(p1, p2, p3, p4, p5, p6), f2_(p1, p2, p3, p4, p5, p6); } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { + return f1_(p1, p2, p3, p4, p5, p6, p7), + f2_(p1, p2, p3, p4, p5, p6, p7); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8), + f2_(p1, p2, p3, p4, p5, p6, p7, p8); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + NewRType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15); + } + + private: + Fun1 f1_; + Fun2 f2_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Chain +// Chains two functor calls one after another +//////////////////////////////////////////////////////////////////////////////// + + + template + Fun2 Chain( + const Fun1& fun1, + const Fun2& fun2) + { + // + // VC7 don't support the auto_ptr tricks + // + std::auto_ptr apParam + ( + new Chainer(fun1, fun2) + ); + + return Fun2(apParam); + } + +} // 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 12, 2002: ported by Benjamin Kaufmann to MSVC 6 +//////////////////////////////////////////////////////////////////////////////// + +#endif // FUNCTOR_INC_ diff --git a/MSVC/1200/HierarchyGenerators.h b/MSVC/1200/HierarchyGenerators.h new file mode 100644 index 0000000..bbc4e81 --- /dev/null +++ b/MSVC/1200/HierarchyGenerators.h @@ -0,0 +1,460 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 24, 2002 + +#ifndef HIERARCHYGENERATORS_INC_ +#define HIERARCHYGENERATORS_INC_ + +#define IS_TYPELIST(TList) TL::Private::IsTypelist + +#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 +// 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 struct TestUnit {}; +// void Func(TestUnit); +// int main() +// { +// GenScatterHierarchy, TestUnit> obj; +// Func(obj); // calls Func(TestUnit) +// } +// +// Using this port the code would become: +// class Foo {}; +// template struct TestUnit {}; +// struct TestUnitWrapper +// { +// template struct In {typedef TestUnit type}; +// }; +// void Func(TestUnit); +// int main() +// { +// GenScatterHierarchy, TestUnitWrapper> obj; +// Func(obj); // calls Func(TestUnit) +// } +// +// Not very nice, i know :-( +// +// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus +// (http://lists.boost.org/MailArchives/boost/msg20915.php) + + template class GenScatterHierarchy; + +namespace Private +{ + template + class InheritFromTwo : public T, public U + { + public: + }; + + template + struct GenScatterImpl; + + // Specialization for a general typelist + template <> + struct GenScatterImpl + { + template + struct In : public GenScatterHierarchy + { + typedef + InheritFromTwo < GenScatterHierarchy, + GenScatterHierarchy + > type; + typedef GenScatterHierarchy LeftBase; + typedef GenScatterHierarchy RightBase; + }; + }; + + // Specialization for a single type + template <> + struct GenScatterImpl + { + template + struct In + { + typedef typename + ApplyInnerType::type type; + typedef type LeftBase; + typedef EmptyType RightBase; + }; + }; + + // Specialization for NullType + template <> + struct GenScatterImpl + { + template + struct In + { + typedef EmptyType type; + typedef type LeftBase; + typedef type RightBase; + }; + }; +} // end namespace Private + + template + class GenScatterHierarchy : public Private::GenScatterImpl + < + IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID : + TL::Private::NoneList_ID + >::template In::type + { + public: + typedef typename Select + < + TL::Private::IsTypelist::value, T, void + >::Result TList; + typedef typename Private::GenScatterImpl + < + IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID : + TL::Private::NoneList_ID + >::template In::LeftBase LeftBase; + + typedef typename Private::GenScatterImpl + < + IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID : + IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID : + TL::Private::NoneList_ID + >::template In::RightBase RightBase; + + template struct Rebind + { + typedef ApplyInnerType::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(obj) +// returns a reference to Unit, where Unit is the template used to generate H +//////////////////////////////////////////////////////////////////////////////// + template + typename ApplyInnerType::type& + Field(GenScatterHierarchy& obj) + { + return obj; + } + + template + const typename ApplyInnerType::type& + Field(const GenScatterHierarchy& obj) + { + return obj; + } + + + +//////////////////////////////////////////////////////////////////////////////// +// function template TupleUnit +// The building block of tuples +//////////////////////////////////////////////////////////////////////////////// + + template + 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 + struct In + { + typedef TupleUnit type; + }; + }; + } + template + struct Tuple : public GenScatterHierarchy + { + }; + +//////////////////////////////////////////////////////////////////////////////// +// helper class template FieldHelper +// See Field below +//////////////////////////////////////////////////////////////////////////////// + + template + struct FieldHelper + { + template + struct In + { + private: + typedef typename TL::TypeAt::Result ElementType; + typedef typename ApplyInnerType::type UnitType; + + enum { isConst = TypeTraits::isConst }; + + typedef typename Select + < + isConst, + const typename H::RightBase, + typename H::RightBase + > + ::Result RightBase; + + + typedef typename Select + < + IsEqualType >::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 + static ResultType& Do(T& obj) + { + typedef typename T::RightBase RightBase; + RightBase& rightBase = obj; + return FieldHelper::template In::Do(rightBase); + } + }; + }; + + template <> + struct FieldHelper<0> + { + template + struct In + { + private: + typedef typename H::TList::Head ElementType; + typedef typename ApplyInnerType::type UnitType; + + enum { isConst = TypeTraits::isConst }; + + typedef typename Select + < + isConst, + const typename H::LeftBase, + typename H::LeftBase + > + ::Result LeftBase; + + typedef typename Select + < + IsEqualType >::value, + ElementType, + UnitType + > + ::Result UnqualifiedResultType; + + public: + typedef typename Select + < + isConst, + const UnqualifiedResultType, + UnqualifiedResultType + > + ::Result ResultType; + + public: + template + static ResultType& Do(T& 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(obj) +// returns a reference to Unit, where Unit is the template used to generate H +// and T is the i-th type in the typelist +//////////////////////////////////////////////////////////////////////////////// + + template + typename FieldHelper::template In,UnitWrapper>::ResultType& + Field(GenScatterHierarchy& obj) + { + typedef typename GenScatterHierarchy H; + + return FieldHelper::template In::Do(obj); + } + + +//////////////////////////////////////////////////////////////////////////////// +// class template GenLinearHierarchy +// Generates a linear hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Model is a template of two args): +// GenScatterHierarchy +//////////////////////////////////////////////////////////////////////////////// +// VC 6.0 changes: +// see GenScatterHierarchy + + template + < + class TList, + class Unit, + class Root = EmptyType + > + class GenLinearHierarchy; + +namespace Private +{ + + template + struct GenLinearHierarchyHelper + { + template + struct In + { + typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result; + }; + }; + + template <> + struct GenLinearHierarchyHelper + { + template + struct In + { + private: + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + public: + typedef ApplyInnerType2 >::type Result; + }; + }; + + template <> + struct GenLinearHierarchyHelper + { + template + struct In + { + private: + typedef typename TList::Head Head; + + public: + typedef ApplyInnerType2::type Result; + }; + }; + + template + struct Wrap + { + struct Dummy {}; + typedef typename T::Tail Tail; + + // create the hierarchy + typedef typename Private::GenLinearHierarchyHelper + < + typename TL::Private::IsTypelist::type_tag + > + ::template In::Result TempType; + + typedef typename + Private::VC_Base_Workaround 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 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::Base + { + ASSERT_TYPELIST(TList); // TList must not be NullType + + public: + typedef typename Private::GenLinearHierarchyHelper + < + typename TL::Private::IsTypelist::type_tag + > + ::template In::Result LinBase; + }; + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// 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 +//////////////////////////////////////////////////////////////////////////////// +#undef IS_TYPELIST +#endif // HIERARCHYGENERATORS_INC_ diff --git a/MSVC/1200/MSVC6Helpers.h b/MSVC/1200/MSVC6Helpers.h new file mode 100644 index 0000000..dab78f3 --- /dev/null +++ b/MSVC/1200/MSVC6Helpers.h @@ -0,0 +1,157 @@ +#ifndef MSVC6HELPERS__H +#define MSVC6HELPERS__H +#if !defined (_MSC_VER) || _MSC_VER >= 1300 +#error "please use this header only with MSVC 6.0" +#endif +namespace Loki +{ + namespace Private + { + // 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 + 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 {}; + + // workarounds for template template parameters +//////////////////////////////////////////////////////////////////////////////// +// class template AlwaysFalse +// Invocation: AlwaysFalse::value +// value will always by 0 (false) +//////////////////////////////////////////////////////////////////////////////// + template< typename T > + struct AlwaysFalse + { + enum { value = false }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ApplyImpl1 +// Invocation: ApplyImpl1::template Result +// T must be a nontemplate type with a nested class template named In. +// The class template is a helper for the Apply1-Template +//////////////////////////////////////////////////////////////////////////////// + template + struct ApplyImpl1 + { + template + struct VC_WORKAROUND : public TypeWithNestedTemplate {}; + + struct VC_WORKAROUND + { template struct In; }; + + template< typename T1 > struct Result : public + VC_WORKAROUND< AlwaysFalse::value >::template In + { + typedef VC_WORKAROUND< AlwaysFalse::value >::template In Base; + + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template ApplyImpl2 +// Invocation: ApplyImpl2::template Result +// T must be a nontemplate type with a nested class template named In. +// The class template is a helper for the Apply2-Template +//////////////////////////////////////////////////////////////////////////////// + template + struct ApplyImpl2 + { + template + struct VC_WORKAROUND : public TypeWithNestedTemplate {}; + + struct VC_WORKAROUND + {template struct In; }; + + template< typename T1, typename T2 > struct Result : public + VC_WORKAROUND< AlwaysFalse::value >::template In + { + }; + }; + + } // end of namespace Private + + +//////////////////////////////////////////////////////////////////////////////// +// class template Apply1 +// Invocation: Apply1 +// 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 + struct Apply1 : Private::ApplyImpl1::template Result + { + typedef typename Private::ApplyImpl1::template Result::Base Base; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template Apply2 +// Invocation: Apply2 +// 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 + struct Apply2 : Private::ApplyImpl2::template Result + { + + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ApplyInnerType +// Invocation: ApplyInnerType::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 + struct ApplyInnerType + { + template struct Wrapper_VC : Wrapper {}; + + template<> struct Wrapper_VC + { template struct In; }; + typedef typename + Wrapper_VC::value>::template In::type type; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template ApplyInnerType2 +// Invocation: ApplyInnerType2::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 + struct ApplyInnerType2 + { + template struct Wrapper_VC : Wrapper {}; + + template<> struct Wrapper_VC + { template struct In; }; + typedef typename + Wrapper_VC::value>::template In::type type; + }; + + template + struct ApplyInnerType4 + { + template struct Wrapper_VC : Wrapper {}; + + template<> struct Wrapper_VC + { template struct In; }; + typedef typename + Wrapper_VC::value>::template In::type type; + }; + +} +#endif \ No newline at end of file diff --git a/MSVC/1200/MultiMethods.h b/MSVC/1200/MultiMethods.h new file mode 100644 index 0000000..12aa4a8 --- /dev/null +++ b/MSVC/1200/MultiMethods.h @@ -0,0 +1,466 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 28, 2002 +// Because MSVC 6.0 does not allow a functions with a return +// type of cv void to return an expression of type "cv void" (6.6.3), this +// port currently *does not* support void as return type. +// +// Because the VC 6.0 does not support explicit template argument specification +// for member functions (14.8.1), I added dummy parameters to functions +// requiring this feature. +// For example: +// The original declaration of BasicDispatcher::Add looks like this: +// +// template +// void Add(CallbackType fun); + +// and you call it like this: +// obj.Add(yourFun); +// +// This port uses: +// +// template +// void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2); +// +// and you call it like this: +// obj.Add(yourFun, (Type1*)0, (Type2*)0); + + +#ifndef MULTIMETHODS_INC_ +#define MULTIMETHODS_INC_ + +#include "Typelist.h" +#include "TypeInfo.h" +#include "Functor.h" +#include "AssocVector.h" + +//////////////////////////////////////////////////////////////////////////////// +// IMPORTANT NOTE: +// The double dispatchers implemented below differ from the excerpts shown in +// the book - they are simpler while respecting the same interface. +//////////////////////////////////////////////////////////////////////////////// + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template InvocationTraits (helper) +// Helps implementing optional symmetry +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + struct InvocationTraits + { + static ResultType + DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type) + { + return exec.Fire(lhs, rhs); + } + static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs, + Executor& exec, Int2Type) + { + 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 = int/*void*/ + > + class StaticDispatcher + { + template + static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs, + Executor exec, NullType) + { return exec.OnError(lhs, rhs); } + + template + static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, + Executor exec, Typelist) + { + if (Head* p2 = dynamic_cast(&rhs)) + { + Int2Type<(symmetric && + int(TL::IndexOf::value) < + int(TL::IndexOf::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 + static ResultType DispatchLhs( BaseLhs& lhs, BaseRhs& rhs, + Executor exec, Typelist) + { + if (Head* p1 = dynamic_cast(&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 = int/*void*/, + typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&) + > + class BasicDispatcher + { + typedef std::pair KeyType; + typedef CallbackType MappedType; + typedef AssocVector MapType; + MapType callbackMap_; + + void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun); + bool DoRemove(TypeInfo lhs, TypeInfo rhs); + + public: + template + void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2) + { + DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun); + } + + template + bool Remove(SomeLhs pDummy1, SomeRhs pDummy2) + { + return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); + } + + ResultType Go(BaseLhs& lhs, BaseRhs& rhs); + }; + + // Non-inline to reduce compile time overhead... + template + void BasicDispatcher + ::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun) + { + callbackMap_[KeyType(lhs, rhs)] = fun; + } + + template + bool BasicDispatcher + ::DoRemove(TypeInfo lhs, TypeInfo rhs) + { + return callbackMap_.erase(KeyType(lhs, rhs)) == 1; + } + + template + ResultType BasicDispatcher + ::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); + } + + struct BasicDispatcherWrapper + { + template + struct In + { + typedef BasicDispatcher type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template StaticCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template + struct StaticCaster + { + static To& Cast(From& obj) + { + return static_cast(obj); + } + }; + struct StaticCasterWrapper + { + template + struct In + { + typedef StaticCaster type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template DynamicCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template + struct DynamicCaster + { + static To& Cast(From& obj) + { + return dynamic_cast(obj); + } + }; + struct DynamicCasterWrapper + { + template + struct In + { + typedef DynamicCaster type; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// 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 FnDispatcher + { + ApplyInnerType4::type backEnd_; + + public: + template + void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&), SomeLhs* pDummy1, SomeRhs* pDummy2) + { + return backEnd_.Add(pFun, pDummy1, pDummy2); + } + + template + void Add(SomeLhs* pDummy1, SomeRhs* pDummy2) + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + typename ApplyInnerType2::type, + typename ApplyInnerType2::type, + callback> Local; + + Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); + } + + template + void Add(SomeLhs* pDummy1, SomeRhs* pDummy2, bool Symmetric) + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + typename ApplyInnerType2::type, + typename ApplyInnerType2::type, + callback> Local; + + Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); + if (Symmetric) + { + Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); + } + } + + template + void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2) + { + backEnd_.Remove(pDummy1, pDummy2); + } + + 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 FunctorDispatcherHelper + { + Fun fun_; + ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type) + { + return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); + } + ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type) + { + 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()); + } + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorDispatcher +// Implements a logarithmic double dispatcher for functors +// Features automated casting +//////////////////////////////////////////////////////////////////////////////// + + template + class FunctorDispatcher + { + typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; + typedef Functor FunctorType; + + ApplyInnerType4::type backEnd_; + + public: + template + void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2) + { + typedef typename ApplyInnerType2::type CastOne; + typedef typename ApplyInnerType2::type CastTwo; + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastOne, + CastTwo, + Fun, false> Adapter; + + + + backEnd_.Add(FunctorType(Adapter(fun), (int*) 0), pDummy1, pDummy2); + } + template + void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2, bool symmetric) + { + Add(fun, pDummy1, pDummy2); + + if (symmetric) + { + // Note: symmetry only makes sense where BaseLhs==BaseRhs + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseLhs, + SomeLhs, SomeRhs, + ResultType, + ApplyInnerType2::type, + ApplyInnerType2::type, + Fun, true> AdapterR; + + backEnd_.Add(FunctorType(Adapter(fun)), pDummy1, pDummy2); + } + } + + template + void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2) + { + backEnd_.Remove(pDummy1, pDummy2); + } + + 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) +// Oct 28, 2002: ported by Benjamin Kaufmann +//////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/MSVC/1200/NullType.h b/MSVC/1200/NullType.h new file mode 100644 index 0000000..c599315 --- /dev/null +++ b/MSVC/1200/NullType.h @@ -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_ diff --git a/MSVC/1200/Readme.txt b/MSVC/1200/Readme.txt new file mode 100644 index 0000000..7d436ee --- /dev/null +++ b/MSVC/1200/Readme.txt @@ -0,0 +1,239 @@ +Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors +------------------------------------------------------------------- + +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. + + +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 a default type void +F. return statements with an expression of type cv in functions with a return type of cv void. +G. Template-ctor resp. template assignment operator + +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 leads + 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 + struct Foo + { + // 'error C1001 - Internal Compiler Error' here + typedef typename APolicy::template In 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 + T Func(); + }; + [/code] + becomes + [code] + struct Foo + { + template + T Func(T* pDummy1); + }; + [/code] + in this port. + + + 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. All template parameters that have a default type of void in the original lib now + have int as default type. + + F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent + for the user of Functor. + Because I could not think of any general and transparent workaround I followed different + strategies. In Visitor.h for example I created new classes (and macros) for the void-case. + In other places (for example: MultiMethod.h) this port simply fails to support void as + return type :-( + + G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version + is present. On the other hand the MSVC 6.0 allows explicit template specialization in class + scope. I used this "feature" as a workaround for code like this: + [code] + template + struct Foo + { + Foo(const Foo&); + template + Foo(const Foo&); + }; + [/code] + + Under MSVC 6.0 the above code becomes: + [code] + template + struct Foo + { + template + Foo(const Foo&); + + // copy-ctor for Foos with equal T + // not valid c++ + template <> + Foo(const Foo&); + }; + [/code] + + +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* 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 provides not + all the stuff provided by the original library's version. + + +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. + +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(); + to + ConcProduct* p = aFactory.Create((ConcProduct*)0); + + +8. SmartPtr.h + + * no template template parameters. + (see 7.for a description of the consequences) + + * This port does not specialize std::less + +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. + + +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). + + +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 diff --git a/MSVC/1200/Singleton.cpp b/MSVC/1200/Singleton.cpp new file mode 100644 index 0000000..adfd9c6 --- /dev/null +++ b/MSVC/1200/Singleton.cpp @@ -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(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 +//////////////////////////////////////////////////////////////////////////////// diff --git a/MSVC/1200/Singleton.h b/MSVC/1200/Singleton.h new file mode 100644 index 0000000..e30e6fd --- /dev/null +++ b/MSVC/1200/Singleton.h @@ -0,0 +1,480 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 07, 2002 + +#ifndef SINGLETON_INC_ +#define SINGLETON_INC_ + +#include "Threads.h" +#include "MSVC6Helpers.h" // for apply-template +#include +#include +#include +#include +#include + +#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 + struct Deleter + { + static void Delete(T* pObj) + { delete pObj; } + }; + + // Concrete lifetime tracker for objects of type T + template + 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 + void SetLongevity(T* pDynObject, unsigned int longevity, + Destroyer d = Private::Deleter::Delete) + { + using namespace Private; + + TrackerArray pNewArray = static_cast( + 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( + 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 + static T* Create(const volatile T* p = 0) + { + return new T; + } + template + 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 + static T* Create(const volatile T* p = 0) + { + void* p = VC_BROKEN_STD::malloc(sizeof(T)); + if (!p) return 0; + return new(p) T; + } + + template + 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 + 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 + static T* Create(const volatile T* p = 0) + { + static MaxAlign staticMemory_; + return new(&staticMemory_) T; + } + + template + static void Destroy(T* p) + { + p->~T(); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultLifetime +// Implementation of the LifetimePolicy used by SingletonHolder +// Schedules an object's destruction as per C++ rules +// Forwards to std::atexit +//////////////////////////////////////////////////////////////////////////////// + + struct DefaultLifetime + { + template + static void ScheduleDestruction(T*, void (*pFun)()) + { VC_BROKEN_STD::atexit(pFun); } + + template + static void OnDeadReference(const volatile T* p = 0 ) + { 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 +//////////////////////////////////////////////////////////////////////////////// + + + class PhoenixSingleton + { + private: + template + struct StaticData + { + static bool destroyedOnce_; + }; + public: + template + static void ScheduleDestruction(T*, void (*pFun)()) + { + +#ifndef ATEXIT_FIXED + if (!StaticData::destroyedOnce_) +#endif + VC_BROKEN_STD::atexit(pFun); + } + + template + static void OnDeadReference(const volatile T* p = 0 ) + { +#ifndef ATEXIT_FIXED + StaticData::destroyedOnce_ = true; + +#endif + } + + }; +#ifndef ATEXIT_FIXED + template + bool ::Loki::PhoenixSingleton::StaticData::destroyedOnce_ = false; +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// class template Adapter +// Helper for SingletonWithLongevity below +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + 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 + static void ScheduleDestruction(T* pObj, void (*pFun)()) + { + Private::Adapter adapter; + adapter.pFun_ = pFun ; + SetLongevity(pObj, GetLongevity(pObj), adapter); + } + + template + static void OnDeadReference(const volatile T* p = 0 ) + { throw std::logic_error("Dead Reference Detected"); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDestroy +// Implementation of the LifetimePolicy used by SingletonHolder +// Never destroys the object +//////////////////////////////////////////////////////////////////////////////// + + + struct NoDestroy + { + template + static void ScheduleDestruction(T*, void (*)()) + {} + + template + 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::VolatileType VolatileType; + static VolatileType pInstance_; + static bool destroyed_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// SingletonHolder's data +//////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + class C, + class L, + class M + > + typename SingletonHolder::VolatileType + SingletonHolder::pInstance_; + + template + < + class T, + class C, + class L, + class M + > + bool SingletonHolder::destroyed_; + +//////////////////////////////////////////////////////////////////////////////// +// SingletonHolder::Instance +//////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + class CreationPolicy, + class LifetimePolicy, + class ThreadingModel + > + inline T& SingletonHolder::Instance() + { + if (!pInstance_) + { + MakeInstance(); + } + return *pInstance_; + } + +//////////////////////////////////////////////////////////////////////////////// +// SingletonHolder::MakeInstance (helper for Instance) +//////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + class CreationPolicy, + class LifetimePolicy, + class ThreadingModel + > + void SingletonHolder::MakeInstance() + { + typename Apply1::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::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 +//////////////////////////////////////////////////////////////////////////////// + +#endif // SINGLETON_INC_ diff --git a/MSVC/1200/SmallObj.cpp b/MSVC/1200/SmallObj.cpp new file mode 100644 index 0000000..050dca0 --- /dev/null +++ b/MSVC/1200/SmallObj.cpp @@ -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 +#include +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(p); + // Alignment check + assert((toRelease - pData_) % blockSize == 0); + + *toRelease = firstAvailableBlock_; + firstAvailableBlock_ = static_cast( + (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(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 +//////////////////////////////////////////////////////////////////////////////// diff --git a/MSVC/1200/SmallObj.h b/MSVC/1200/SmallObj.h new file mode 100644 index 0000000..0f74b48 --- /dev/null +++ b/MSVC/1200/SmallObj.h @@ -0,0 +1,193 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 11, 2002 + +#ifndef SMALLOBJ_INC_ +#define SMALLOBJ_INC_ + +#include "Threads.h" +#include "Singleton.h" +#include "MSVC6Helpers.h" // for apply-template +#include +#include +#ifdef _MSC_VER +#define for if(0);else for +# pragma warning(disable:4291) +#endif + +#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 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 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 > + { + typedef typename Apply1 > 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 MyAllocator; + + public: + static void* operator new(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 + + return SingletonHolder::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::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_ diff --git a/MSVC/1200/SmartPtr.h b/MSVC/1200/SmartPtr.h new file mode 100644 index 0000000..de1c575 --- /dev/null +++ b/MSVC/1200/SmartPtr.h @@ -0,0 +1,1447 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 26, 2002 +// replaced all template template parameters with 'normal' parameters +// For each Policy there is now a wrapper-class (non template class) +// containing a nested template class called In which +// provides a typedef (type) to the real Policy-class +// +// VC special: The MSVC 6.0 has problems with template ctors resp. template +// assignemt operators. If there exists a template copy ctor (a template op=) the +// compiler will complain about a non-template version. On the other hand, +// if one does not provide a non-template version and one tries to +// initialize a new object with one having the same type the compiler will synthesize +// a default version (the same for assignment). +// Because the MSVC allows explicit specialization in class scope i used +// this as a workaround. +// Instead of: +// template +// struct Foo +// { +// Foo(const Foo&) +// {} +// template +// Foo(const Foo& r) +// {} +// }; +// +// this port uses: +// +// template +// struct Foo +// { +// template +// Foo(const Foo& r) +// {} +// template <> +// Foo(const Foo& r) +// {} +// }; + +#ifndef SMARTPTR_INC_ +#define SMARTPTR_INC_ + +//////////////////////////////////////////////////////////////////////////////// +// IMPORTANT NOTE +// Due to threading issues, the OwnershipPolicy has been changed as follows: +// Release() returns a boolean saying if that was the last release +// so the pointer can be deleted by the StoragePolicy +// IsUnique() was removed +//////////////////////////////////////////////////////////////////////////////// + + +#include "SmallObj.h" +#include "TypeManip.h" +#include "MSVC6Helpers.h" +#include "static_check.h" +#include +#include +#include + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultSPStorage +// Implementation of the StoragePolicy used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + class DefaultSPStorage + { + public: + typedef T* StoredType; // the type of the pointee_ object + typedef T* PointerType; // type returned by operator-> + typedef T& ReferenceType; // type returned by operator* + + public: + DefaultSPStorage() : pointee_(Default()) + {} + + // The storage policy doesn't initialize the stored pointer + // which will be initialized by the OwnershipPolicy's Clone fn +#if !defined(_MSC_VER) + DefaultSPStorage(const DefaultSPStorage&) + {} +#endif + template + DefaultSPStorage(const DefaultSPStorage&) + {} +#if _MSC_VER <= 1200 + template <> + DefaultSPStorage(const DefaultSPStorage&) + {} +#endif + DefaultSPStorage(const StoredType& p) : pointee_(p) {} + + PointerType operator->() const { return pointee_; } + + ReferenceType operator*() const { return *pointee_; } + + void Swap(DefaultSPStorage& rhs) + { std::swap(pointee_, rhs.pointee_); } + + // Accessors + friend inline PointerType GetImpl(const DefaultSPStorage& sp) + { return sp.pointee_; } + + friend inline const StoredType& GetImplRef(const DefaultSPStorage& sp) + { return sp.pointee_; } + + friend inline StoredType& GetImplRef(DefaultSPStorage& sp) + { return sp.pointee_; } + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + void Destroy() + { delete pointee_; } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + // Data + StoredType pointee_; + }; + + struct DefaultSPStorageWrapper + { + template + struct In + { + typedef DefaultSPStorage type; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template RefCounted +// Implementation of the OwnershipPolicy used by SmartPtr +// Provides a classic external reference counting implementation +//////////////////////////////////////////////////////////////////////////////// + + template + class RefCounted + { + public: + RefCounted() + { + pCount_ = static_cast( + SmallObject<>::operator new(sizeof(unsigned int))); + assert(pCount_); + *pCount_ = 1; + } + +#if !defined(_MSC_VER) + RefCounted(const RefCounted& rhs) + : pCount_(rhs.pCount_) + {} +#endif + + // MWCW lacks template friends, hence the following kludge + template + RefCounted(const RefCounted& rhs) + : pCount_(reinterpret_cast(rhs).pCount_) + {} + +#if _MSC_VER <= 1200 + template<> + RefCounted(const RefCounted& rhs) + : pCount_(rhs.pCount_) + {} +#endif + P Clone(const P& val) + { + ++*pCount_; + return val; + } + + bool Release(const P&) + { + if (!--*pCount_) + { + SmallObject<>::operator delete(pCount_, sizeof(unsigned int)); + return true; + } + return false; + } + + void Swap(RefCounted& rhs) + { std::swap(pCount_, rhs.pCount_); } + + enum { destructiveCopy = false }; + + private: + // Data + unsigned int* pCount_; + }; + + + struct RefCountedWrapper + { + template + struct In + { + typedef RefCounted type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template RefCountedMT +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements external reference counting for multithreaded programs +//////////////////////////////////////////////////////////////////////////////// +// Note: I could not figure out how this class is supposed to work. Therefore +// i could not port it. +// pCount has type volatile unsigned int but the different Thread-Policies +// expect volatile int& resp. volatile long& +// :-( + + /* + template class ThreadingModel> + class RefCountedMT : public ThreadingModel< RefCountedMT > + { + public: + RefCountedMT() + { + pCount_ = static_cast( + SmallObject::operator new( + sizeof(unsigned int))); + assert(pCount_); + *pCount_ = 1; + } + + RefCountedMT(const RefCountedMT& rhs) + : pCount_(rhs.pCount_) + {} + + // MWCW lacks template friends, hence the following kludge + template + RefCountedMT(const RefCountedMT& rhs) + : pCount_(reinterpret_cast&>(rhs).pCount_) + {} + + P Clone(const P& val) + { + ThreadingModel::AtomicIncrement(*pCount_); + return val; + } + + bool Release(const P&) + { + if (!ThreadingModel::AtomicDecrement(*pCount_)) + { + SmallObject::operator delete(pCount_, + sizeof(unsigned int)); + return true; + } + return false; + } + + void Swap(RefCountedMT& rhs) + { std::swap(pCount_, rhs.pCount_); } + + enum { destructiveCopy = false }; + + private: + // Data + volatile unsigned int* pCount_; + };*/ +//////////////////////////////////////////////////////////////////////////////// +// class template COMRefCounted +// Implementation of the OwnershipPolicy used by SmartPtr +// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax +//////////////////////////////////////////////////////////////////////////////// + + template + class COMRefCounted + { + public: + COMRefCounted() + {} + + template + COMRefCounted(const COMRefCounted&) + {} + + static P Clone(const P& val) + { + val->AddRef(); + return val; + } + + static bool Release(const P& val) + { val->Release(); return false; } + + enum { destructiveCopy = false }; + + static void Swap(COMRefCounted&) + {} + }; + + struct COMRefCountedWrapper + { + template + struct In + { + typedef COMRefCounted type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template DeepCopy +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements deep copy semantics, assumes existence of a Clone() member +// function of the pointee type +//////////////////////////////////////////////////////////////////////////////// + + template + struct DeepCopy + { + DeepCopy() + {} + + template + DeepCopy(const DeepCopy&) + {} + + static P Clone(const P& val) + { return val->Clone(); } + + static bool Release(const P& val) + { return true; } + + static void Swap(DeepCopy&) + {} + + enum { destructiveCopy = false }; + }; + + struct DeepCopyWrapper + { + template + struct In + { + typedef DeepCopy type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template RefLinked +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements reference linking +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + class RefLinkedBase + { + public: + RefLinkedBase() + { prev_ = next_ = this; } + + RefLinkedBase(const RefLinkedBase& rhs) + { + prev_ = &rhs; + next_ = rhs.next_; + prev_->next_ = this; + next_->prev_ = this; + } + + bool Release() + { + if (next_ == this) + { + assert(prev_ == this); + return true; + } + prev_->next_ = next_; + next_->prev_ = prev_; + return false; + } + + void Swap(RefLinkedBase& rhs) + { + if (next_ == this) + { + assert(prev_ == this); + if (rhs.next_ == &rhs) + { + assert(rhs.prev_ == &rhs); + // both lists are empty, nothing 2 do + return; + } + prev_ = rhs.prev_; + next_ = rhs.next_; + prev_->next_ = next_->prev_ = this; + rhs.next_ = rhs.prev_ = &rhs; + return; + } + if (rhs.next_ == &rhs) + { + rhs.Swap(*this); + return; + } + std::swap(prev_, rhs.prev_); + std::swap(next_, rhs.next_); + std::swap(prev_->next_, rhs.prev_->next_); + std::swap(next_->prev_, rhs.next_->prev_); + } + + enum { destructiveCopy = false }; + + private: + mutable const RefLinkedBase* prev_; + mutable const RefLinkedBase* next_; + }; + } + + + template + class RefLinked : public Private::RefLinkedBase + { + public: + RefLinked() + {} + + template + RefLinked(const RefLinked& rhs) + : Private::RefLinkedBase(rhs) + {} + + static P Clone(const P& val) + { return val; } + + bool Release(const P&) + { typedef Private::RefLinkedBase MyBase; + return this->MyBase::Release(); + } + }; + + struct RefLinkedWrapper + { + template + struct In + { + typedef RefLinked type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template DestructiveCopy +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements destructive copy semantics (a la std::auto_ptr) +//////////////////////////////////////////////////////////////////////////////// + + template + class DestructiveCopy + { + public: + DestructiveCopy() + {} + + template + DestructiveCopy(const DestructiveCopy&) + {} + + template + static P Clone(P1& val) + { + P result(val); + val = P1(); + return result; + } + + static bool Release(const P&) + { return true; } + + static void Swap(DestructiveCopy&) + {} + + enum { destructiveCopy = true }; + }; + struct DestructiveCopyWrapper + { + template + struct In + { + typedef DestructiveCopy type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template NoCopy +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements a policy that doesn't allow copying objects +//////////////////////////////////////////////////////////////////////////////// + + template + class NoCopy + { + public: + NoCopy() + {} + + template + NoCopy(const NoCopy&) + {} + + static P Clone(const P&) + { + CT_ASSERT(false, This_Policy_Disallows_Value_Copying); + } + + static bool Release(const P&) + { return true; } + + static void Swap(NoCopy&) + {} + + enum { destructiveCopy = false }; + }; + + struct NoCopyWrapper + { + template + struct In + { + typedef NoCopy type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template AllowConversion +// Implementation of the ConversionPolicy used by SmartPtr +// Allows implicit conversion from SmartPtr to the pointee type +//////////////////////////////////////////////////////////////////////////////// + + struct AllowConversion + { + enum { allow = true }; + + void Swap(AllowConversion&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DisallowConversion +// Implementation of the ConversionPolicy used by SmartPtr +// Does not allow implicit conversion from SmartPtr to the pointee type +// You can initialize a DisallowConversion with an AllowConversion +//////////////////////////////////////////////////////////////////////////////// + + struct DisallowConversion + { + DisallowConversion() + {} + + DisallowConversion(const AllowConversion&) + {} + + enum { allow = false }; + + void Swap(DisallowConversion&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoCheck +// Implementation of the CheckingPolicy used by SmartPtr +// Well, it's clear what it does :o) +//////////////////////////////////////////////////////////////////////////////// + + template + struct NoCheck + { + NoCheck() + {} + + template + NoCheck(const NoCheck&) + {} + + static void OnDefault(const P&) + {} + + static void OnInit(const P&) + {} + + static void OnDereference(const P&) + {} + + static void Swap(NoCheck&) + {} + }; + + struct NoCheckWrapper + { + template + struct In + { + typedef NoCheck type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template AssertCheck +// Implementation of the CheckingPolicy used by SmartPtr +// Checks the pointer before dereference +//////////////////////////////////////////////////////////////////////////////// + + template + struct AssertCheck + { + AssertCheck() + {} + + template + AssertCheck(const AssertCheck&) + {} + + template + AssertCheck(const NoCheck&) + {} + + static void OnDefault(const P&) + {} + + static void OnInit(const P&) + {} + + static void OnDereference(P val) + { assert(val); } + + static void Swap(AssertCheck&) + {} + }; + + struct AssertCheckWrapper + { + template + struct In {typedef AssertCheck type;}; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template AssertCheckStrict +// Implementation of the CheckingPolicy used by SmartPtr +// Checks the pointer against zero upon initialization and before dereference +// You can initialize an AssertCheckStrict with an AssertCheck +//////////////////////////////////////////////////////////////////////////////// + + template + struct AssertCheckStrict + { + AssertCheckStrict() + {} + + template + AssertCheckStrict(const AssertCheckStrict&) + {} + + template + AssertCheckStrict(const AssertCheck&) + {} + + template + AssertCheckStrict(const NoCheck&) + {} + + static void OnDefault(P val) + { assert(val); } + + static void OnInit(P val) + { assert(val); } + + static void OnDereference(P val) + { assert(val); } + + static void Swap(AssertCheckStrict&) + {} + }; + + struct AssertCheckStrictWrapper + { + template + struct In + { + typedef AssertCheckStrict type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class NullPointerException +// Used by some implementations of the CheckingPolicy used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + struct NullPointerException : public std::runtime_error + { + NullPointerException() : std::runtime_error("") + { } + const char* what() const throw() + { return "Null Pointer Exception"; } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template RejectNullStatic +// Implementation of the CheckingPolicy used by SmartPtr +// Checks the pointer upon initialization and before dereference +//////////////////////////////////////////////////////////////////////////////// + + template + struct RejectNullStatic + { + RejectNullStatic() + {} + + template + RejectNullStatic(const RejectNullStatic&) + {} + + template + RejectNullStatic(const NoCheck&) + {} + + template + RejectNullStatic(const AssertCheck&) + {} + + template + RejectNullStatic(const AssertCheckStrict&) + {} + + static void OnDefault(const P&) + { + CompileTimeError + ERROR_This_Policy_Does_Not_Allow_Default_Initialization; + } + + static void OnInit(const P& val) + { if (!val) throw NullPointerException(); } + + static void OnDereference(const P& val) + { if (!val) throw NullPointerException(); } + + static void Swap(RejectNullStatic&) + {} + }; + + struct RejectNullStaticWrapper + { + template + struct In + { + typedef RejectNullStatic type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template RejectNull +// Implementation of the CheckingPolicy used by SmartPtr +// Checks the pointer before dereference +//////////////////////////////////////////////////////////////////////////////// + + template + struct RejectNull + { + RejectNull() + {} + + template + RejectNull(const RejectNull&) + {} + + static void OnInit(P val) + { if (!val) throw NullPointerException(); } + + static void OnDefault(P val) + { OnInit(val); } + + void OnDereference(P val) + { OnInit(val); } + + void Swap(RejectNull&) + {} + }; + + struct RejectNullWrapper + { + template + struct In + { + typedef RejectNull type; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template RejectNullStrict +// Implementation of the CheckingPolicy used by SmartPtr +// Checks the pointer upon initialization and before dereference +//////////////////////////////////////////////////////////////////////////////// + + template + struct RejectNullStrict + { + RejectNullStrict() + {} + + template + RejectNullStrict(const RejectNullStrict&) + {} + + template + RejectNullStrict(const RejectNull&) + {} + + static void OnInit(P val) + { if (!val) throw NullPointerException(); } + + void OnDereference(P val) + { OnInit(val); } + + void Swap(RejectNullStrict&) + {} + }; + + struct RejectNullStrictWrapper + { + template + struct In + { + typedef RejectNullStrict type; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template ByRef +// Transports a reference as a value +// Serves to implement the Colvin/Gibbons trick for SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + class ByRef + { + public: + ByRef(T& v) : value_(v) {} + operator T&() { return value_; } + // gcc doesn't like this: + // operator const T&() const { return value_; } + private: + T& value_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template SmartPtr (declaration) +// The reason for all the fuss above +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OwnershipPolicy = RefCountedWrapper, + class ConversionPolicy = DisallowConversion, + class CheckingPolicy = AssertCheckWrapper, + class StoragePolicy = DefaultSPStorageWrapper + > + class SmartPtr; + + +//////////////////////////////////////////////////////////////////////////////// +// class template SmartPtr (definition) +//////////////////////////////////////////////////////////////////////////////// + +namespace Private +{ + template + struct SmartPtrImpl + { + struct Dummy{}; + typedef typename ApplyInnerType::type TempType; + typedef VC_Base_Workaround sttype; + // VC 6.0 will emit an "Error C2516. : is not a legal base class" + // if one tries to use TempType as base class for SmartPtr. + // Don't know why the compiler is happy with this workaround + typedef sttype::LeftBase Storage; + typedef Storage::PointerType PointerType; + typedef Storage::StoredType StoredType; + typedef Storage::ReferenceType ReferenceType; + + typedef typename ApplyInnerType::type Temp2Type; + typedef typename ApplyInnerType::type Temp3Type; + + typedef VC_Base_Workaround owtype; + typedef owtype::LeftBase Owner; + + typedef VC_Base_Workaround chtype; + typedef chtype::LeftBase Checking; + + typedef Con Conversion; + }; +} + template + < + typename T, + class OwnershipPolicy, + class ConversionPolicy, + class CheckingPolicy, + class StoragePolicy + > + class SmartPtr + : public Private::SmartPtrImpl::Storage + , public Private::SmartPtrImpl::Owner + , public Private::SmartPtrImpl::Checking + , public Private::SmartPtrImpl::Conversion + { + public: + typedef typename Private::SmartPtrImpl + < + T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy + >::Storage SP; + typedef SP::PointerType PointerType; + typedef SP::StoredType StoredType; + typedef SP::ReferenceType ReferenceType; + + typedef typename Private::SmartPtrImpl + < + T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy + >::Owner OP; + typedef typename Private::SmartPtrImpl + < + T, OwnershipPolicy, ConversionPolicy, CheckingPolicy, StoragePolicy + >::Checking KP; + + typedef ConversionPolicy CP; + typedef typename Select + < + OP::destructiveCopy, + SmartPtr, const SmartPtr + >::Result CopyArg; + + // i think the following two ctors have an exception-safety problem + // in the original version. If KP throws one can't release the resources + // which were possibly allocated by SP and/or OP. + // don't know if my solution works. + SmartPtr() + { + try + { + KP::OnDefault(GetImpl(*this)); + } + catch(...) + { + if (OP::Release(GetImpl(*static_cast(this)))) + { + SP::Destroy(); + } + throw; + } + } + + SmartPtr(const StoredType& p) : SP(p) + { + try + { + KP::OnInit(GetImpl(*this)); + } + catch(...) + { + if (OP::Release(GetImpl(*static_cast(this)))) + { + SP::Destroy(); + } + throw; + } + + } + +#if !defined(_MSC_VER) + SmartPtr(CopyArg& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) +#endif + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + SmartPtr(const SmartPtr& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } + + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + SmartPtr(SmartPtr& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } + +#if _MSC_VER <= 1200 + + template <> + SmartPtr(CopyArg& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) +#endif + + { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } + SmartPtr(ByRef rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + {} + + operator ByRef() + { return ByRef(*this); } +#if !defined(_MSC_VER) + SmartPtr& operator=(CopyArg& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } +#endif + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + SmartPtr& operator=(const SmartPtr& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } + + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + SmartPtr& operator=(SmartPtr& rhs) + { + + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } +#if _MSC_VER <= 1200 + template<> + SmartPtr& operator=(CopyArg& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } +#endif + void Swap(SmartPtr& rhs) + { + OP::Swap(rhs); + CP::Swap(rhs); + KP::Swap(rhs); + SP::Swap(rhs); + } + + ~SmartPtr() + { + if (OP::Release(GetImpl(*static_cast(this)))) + { + SP::Destroy(); + } + } + + friend inline void Release(SmartPtr& sp, StoredType& p) + { + p = GetImplRef(sp); + GetImplRef(sp) = SP::Default(); + } + + friend inline void Reset(SmartPtr& sp, StoredType p) + { SmartPtr(p).Swap(sp); } + + PointerType operator->() + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator->(); + } + + PointerType operator->() const + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator->(); + } + + ReferenceType operator*() + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator*(); + } + + ReferenceType operator*() const + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator*(); + } + + bool operator!() const // Enables "if (!sp) ..." + { return GetImpl(*this) == 0; } + + inline friend bool operator==(const SmartPtr& lhs, + const T* rhs) + { return GetImpl(lhs) == rhs; } + + inline friend bool operator==(const T* lhs, + const SmartPtr& rhs) + { return rhs == lhs; } + + inline friend bool operator!=(const SmartPtr& lhs, + const T* rhs) + { return !(lhs == rhs); } + + inline friend bool operator!=(const T* lhs, + const SmartPtr& rhs) + { return rhs != lhs; } + + // Ambiguity buster + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + bool operator==(const SmartPtr& rhs) const + { return *this == GetImpl(rhs); } + + // Ambiguity buster + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + bool operator!=(const SmartPtr& rhs) const + { return !(*this == rhs); } + + // Ambiguity buster + template + < + typename T1, + class OP1, + class CP1, + class KP1, + class SP1 + > + bool operator<(const SmartPtr& rhs) const + { return *this < GetImpl(rhs); } + + private: + // Helper for enabling 'if (sp)' + struct Tester + { + Tester() {} + private: + void operator delete(void*); + }; + + public: + // enable 'if (sp)' + operator Tester*() const + { + if (!*this) return 0; + static Tester t; + return &t; + } + + private: + // Helper for disallowing automatic conversion + struct Insipid + { + Insipid(PointerType) {} + }; + + typedef typename Select::Result + AutomaticConversionResult; + + public: + operator AutomaticConversionResult() const + { return GetImpl(*this); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// free comparison operators for class template SmartPtr +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// operator== for lhs = SmartPtr, rhs = raw pointer +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator==(const SmartPtr& lhs, + const U* rhs) + { return GetImpl(lhs) == rhs; } + +//////////////////////////////////////////////////////////////////////////////// +// operator== for lhs = raw pointer, rhs = SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator==(const U* lhs, + const SmartPtr& rhs) + { return rhs == lhs; } + +//////////////////////////////////////////////////////////////////////////////// +// operator!= for lhs = SmartPtr, rhs = raw pointer +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator!=(const SmartPtr& lhs, + const U* rhs) + { return !(lhs == rhs); } + +//////////////////////////////////////////////////////////////////////////////// +// operator!= for lhs = raw pointer, rhs = SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator!=(const U* lhs, + const SmartPtr& rhs) + { return rhs != lhs; } + +//////////////////////////////////////////////////////////////////////////////// +// operator< for lhs = SmartPtr, rhs = raw pointer -- NOT DEFINED +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator<(const SmartPtr& lhs, + const U* rhs); + +//////////////////////////////////////////////////////////////////////////////// +// operator< for lhs = raw pointer, rhs = SmartPtr -- NOT DEFINED +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator<(const U* lhs, + const SmartPtr& rhs); + +//////////////////////////////////////////////////////////////////////////////// +// operator> for lhs = SmartPtr, rhs = raw pointer -- NOT DEFINED +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator>(const SmartPtr& lhs, + const U* rhs) + { return rhs < lhs; } + +//////////////////////////////////////////////////////////////////////////////// +// operator> for lhs = raw pointer, rhs = SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator>(const U* lhs, + const SmartPtr& rhs) + { return rhs < lhs; } + +//////////////////////////////////////////////////////////////////////////////// +// operator<= for lhs = SmartPtr, rhs = raw pointer +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator<=(const SmartPtr& lhs, + const U* rhs) + { return !(rhs < lhs); } + +//////////////////////////////////////////////////////////////////////////////// +// operator<= for lhs = raw pointer, rhs = SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator<=(const U* lhs, + const SmartPtr& rhs) + { return !(rhs < lhs); } + +//////////////////////////////////////////////////////////////////////////////// +// operator>= for lhs = SmartPtr, rhs = raw pointer +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator>=(const SmartPtr& lhs, + const U* rhs) + { return !(lhs < rhs); } + +//////////////////////////////////////////////////////////////////////////////// +// operator>= for lhs = raw pointer, rhs = SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + class OP, + class CP, + class KP, + class SP, + typename U + > + inline bool operator>=(const U* lhs, + const SmartPtr& rhs) + { return !(lhs < rhs); } + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// specialization of std::less for SmartPtr +//////////////////////////////////////////////////////////////////////////////// + +// MSVC 6.0 does not support partial template specialization :-( +#if !defined(_MSC_VER) +namespace std +{ + template + < + typename T, + class OP, + class CP, + class KP, + class SP + > + struct less< Loki::SmartPtr > + : public binary_function, + Loki::SmartPtr, bool> + { + bool operator()(const Loki::SmartPtr& lhs, + const Loki::SmartPtr& rhs) const + { return less()(GetImpl(lhs), GetImpl(rhs)); } + }; +} +#endif +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// December 09, 2001: Included +// Oct 26, 2002: ported by Benjamin Kaufmann to MSVC 6.0 +//////////////////////////////////////////////////////////////////////////////// + +#endif // SMARTPTR_INC_ diff --git a/MSVC/1200/Threads.h b/MSVC/1200/Threads.h new file mode 100644 index 0000000..a59d64f --- /dev/null +++ b/MSVC/1200/Threads.h @@ -0,0 +1,219 @@ +#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: Oct 07, 2002 +// note: In this VC 6 port all template policies become non-templates with +// either member-template functions or a nested template struct named In + +#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 + 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 + struct In + { + private: + CRITICAL_SECTION mtx_; + + public: + ObjectLevelLockable() + { + ::InitializeCriticalSection(&mtx_); + } + + ~ObjectLevelLockable() + { + ::DeleteCriticalSection(&mtx_); + } + + class Lock; + friend class Lock; + + class Lock + { + ObjectLevelLockable& host_; + + Lock(const Lock&); + Lock& operator=(const Lock&); + Lock(); // buggy design + public: + + explicit Lock(ObjectLevelLockable& host) : host_(host) + { + ::EnterCriticalSection(&host_.mtx_); + } + ~Lock() + { + ::LeaveCriticalSection(&host_.mtx_); + } + }; + + typedef volatile Host VolatileType; + + typedef LONG IntType; + + static IntType AtomicIncrement(volatile IntType& lval) + { return InterlockedIncrement(&const_cast(lval)); } + + static IntType AtomicDecrement(volatile IntType& lval) + { return InterlockedDecrement(&const_cast(lval)); } + + static void AtomicAssign(volatile IntType& lval, IntType val) + { InterlockedExchange(&const_cast(lval), val); } + + static void AtomicAssign(IntType& lval, volatile IntType& val) + { InterlockedExchange(&lval, val); } + }; + }; + + struct ClassLevelLockable + { + template + struct In + { + private: + 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(lval)); } + + static IntType AtomicDecrement(volatile IntType& lval) + { return InterlockedDecrement(&const_cast(lval)); } + + static void AtomicAssign(volatile IntType& lval, IntType val) + { InterlockedExchange(&const_cast(lval), val); } + + static void AtomicAssign(IntType& lval, volatile IntType& val) + { InterlockedExchange(&lval, val); } + }; + }; + + template + typename ClassLevelLockable::template In::Initializer + ClassLevelLockable::template In::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 +//////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/MSVC/1200/Tuple.h b/MSVC/1200/Tuple.h new file mode 100644 index 0000000..df83859 --- /dev/null +++ b/MSVC/1200/Tuple.h @@ -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 +//////////////////////////////////////////////////////////////////////////////// diff --git a/MSVC/1200/TypeInfo.h b/MSVC/1200/TypeInfo.h new file mode 100644 index 0000000..a98bfe6 --- /dev/null +++ b/MSVC/1200/TypeInfo.h @@ -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 TYPEINFO_INC_ +#define TYPEINFO_INC_ + +#include +#include +#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 // TYPEINFO_INC_ diff --git a/MSVC/1200/TypeManip.h b/MSVC/1200/TypeManip.h new file mode 100644 index 0000000..6728af4 --- /dev/null +++ b/MSVC/1200/TypeManip.h @@ -0,0 +1,268 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 where v is a compile-time constant integral +// Defines 'value', an enum that evaluates to v +//////////////////////////////////////////////////////////////////////////////// + + template + struct Int2Type + { + enum { value = v }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Type2Type +// Converts each type into a unique, insipid type +// Invocation Type2Type where T is a type +// Defines the type OriginalType which maps back to T +//////////////////////////////////////////////////////////////////////////////// + + template + struct Type2Type + { + typedef T OriginalType; + Type2Type() {}; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Select +// Selects one of two types based upon a boolean constant +// Invocation: Select::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 + struct SelectImpl + { + template + struct In + { + typedef T Result; + }; + }; + + template <> + struct SelectImpl + { + template + struct In + { + typedef U Result; + }; + }; + +} // end of namespace private + template + struct Select + { + typedef typename Private::SelectImpl::template In::Result Result; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template IsEqualType +// Returns true if the two given types are equal +// Invocation: IsEqualType::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 + struct IsEqualType + { + private: + static Private::YES check(Type2Type); + static Private::NO check(...); + public: + enum {value = sizeof(check(Type2Type())) == 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 + struct IsVoid + { + enum { value = + IsEqualType::value || + IsEqualType::value || + IsEqualType::value || + IsEqualType::value + }; + }; + } + +// +// is one type convertable to another? +// +// is_convertible from Rani Sharoni's VC 7 port. + template + class is_convertible + { + struct VoidReplace {}; + + typedef typename Select + < + Private::IsVoid::value, + VoidReplace, T + > + ::Result T1; + + typedef typename Select + < + Private::IsVoid::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::exists +// returns (at compile time) true if there is an implicit conversion from T +// to U (example: Derived to Base) +// b) Conversion::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::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 + struct Conversion + { + enum { exists = (is_convertible::exists) }; + enum { exists2Way = (exists && is_convertible::exists) }; + enum { sameType = (IsEqualType::value) }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template SuperSubclass +// Invocation: SuperSubclass::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 +struct SuperSubclass +{ + enum { value = (::Loki::Conversion::exists && + !::Loki::Conversion::sameType) }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template SuperSubclassStrict +// Invocation: SuperSubclassStrict::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 +struct SuperSubclassStrict +{ + enum { value = (::Loki::Conversion::exists && + !::Loki::Conversion::sameType && + !::Loki::Conversion::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::exists && \ + !::Loki::Conversion::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::sameType) + + + +template +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_ + diff --git a/MSVC/1200/TypeTraits.h b/MSVC/1200/TypeTraits.h new file mode 100644 index 0000000..1c6a74d --- /dev/null +++ b/MSVC/1200/TypeTraits.h @@ -0,0 +1,302 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 05, 2002 +// Most of the code is taken from Rani Sharoni's Loki VC 7 port +// Reference, pointer and array detection is based on boost's type traits +// AdjReference has moved to namespace-scope. Explicit specialization is +// only allowed there. + +#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 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 + 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 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 + 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 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 + 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::isPointer +// returns (at compile time) true if T is a pointer type +// b) TypeTraits::PointeeType +// returns the type to which T points is T is a pointer type, NullType otherwise +// a) TypeTraits::isReference +// returns (at compile time) true if T is a reference type +// b) TypeTraits::ReferredType +// returns the type to which T refers is T is a reference type, NullType +// otherwise +// c) TypeTraits::isMemberPointer +// returns (at compile time) true if T is a pointer to member type +// d) TypeTraits::isStdUnsignedInt +// returns (at compile time) true if T is a standard unsigned integral type +// e) TypeTraits::isStdSignedInt +// returns (at compile time) true if T is a standard signed integral type +// f) TypeTraits::isStdIntegral +// returns (at compile time) true if T is a standard integral type +// g) TypeTraits::isStdFloat +// returns (at compile time) true if T is a standard floating-point type +// h) TypeTraits::isStdArith +// returns (at compile time) true if T is a standard arithmetic type +// i) TypeTraits::isStdFundamental +// returns (at compile time) true if T is a standard fundamental type +// j) TypeTraits::isUnsignedInt +// returns (at compile time) true if T is a unsigned integral type +// k) TypeTraits::isSignedInt +// returns (at compile time) true if T is a signed integral type +// l) TypeTraits::isIntegral +// returns (at compile time) true if T is a integral type +// m) TypeTraits::isFloat +// returns (at compile time) true if T is a floating-point type +// n) TypeTraits::isArith +// returns (at compile time) true if T is a arithmetic type +// o) TypeTraits::isFundamental +// returns (at compile time) true if T is a fundamental type +// p) TypeTraits::ParameterType +// returns the optimal type to be used as a parameter for functions that take Ts +// q) TypeTraits::isConst +// returns (at compile time) true if T is a const-qualified type +// r) TypeTraits::NonConstType +// removes the 'const' qualifier from T, if any +// s) TypeTraits::isVolatile +// returns (at compile time) true if T is a volatile-qualified type +// t) TypeTraits::NonVolatileType +// removes the 'volatile' qualifier from T, if any +// u) TypeTraits::UnqualifiedType +// removes both the 'const' and 'volatile' qualifiers from T, if any +//////////////////////////////////////////////////////////////////////////////// + namespace Private + { + struct pointer_helper + { + pointer_helper(const volatile void*); + }; + + struct EnumFalse{ enum {value = 0};}; + struct EnumTrue{ enum {value = 1};}; + template + struct AdjReference + { + template + struct In { typedef U const & Result; }; + }; + + template<> + struct AdjReference + { + template + struct In { typedef U Result; }; + }; + + } + + template + class TypeTraits + { + private: +// static T MakeT(...); + template struct Wrap{}; + struct pointer_helper + { + pointer_helper(const volatile void*); + }; + static Private::YES is_pointer(pointer_helper); + static Private::NO is_pointer(...); + + // With the VC 6. Rani Sharoni's approach to detect references unfortunately + // results in an error C1001: INTERNER COMPILER- FEHLER + // + // is_reference_helper1 is a function taking a Wrap returning + // a pointer to a function taking a Wrap 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 Wrap 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. + // + // this reference-detection approach is based on boost's + // Type-Traits. See: boost::composite_traits.h + template + static T&(* is_reference_helper1(Wrap) )(Wrap); + static Private::NO is_reference_helper1(...); + + template + static Private::NO is_reference_helper2(T&(*)(Wrap)); + static Private::YES is_reference_helper2(...); + + template + static Private::YES is_pointer2member(U T::*); + static Private::NO is_pointer2member(...); + + // This function can only be used for non-array-types, because + // functions can't return arrays. + // this array-detection approach is based on boost's + // Type-Traits. See: boost::array_traits.h + template + static T(* is_array_helper1(Wrap) )(Wrap); + static Private::NO is_array_helper1(...); + + template + static Private::NO is_array_helper2(T(*)(Wrap)); + static Private::YES is_array_helper2(...); + + template + static Private::YES is_const(Wrap); + static Private::NO is_const(...); + + template + static Private::YES is_volatile(Wrap); + static Private::NO is_volatile(...); + public: + enum {isReference = sizeof( + is_reference_helper2( + is_reference_helper1(Wrap()))) == sizeof(Private::YES)}; +// enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)}; +// enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)}; + enum {isArray = sizeof( + is_array_helper1( + is_array_helper2(Wrap()))) == sizeof(Private::YES)}; + enum {isVoid = Private::IsVoid::value}; + + enum { isStdUnsignedInt = + TL::IndexOf::value >= 0 }; + enum { isStdSignedInt = + TL::IndexOf::value >= 0 }; + enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || + TL::IndexOf::value >= 0 }; + enum { isStdFloat = TL::IndexOf::value >= 0 }; + enum { isStdArith = isStdIntegral || isStdFloat }; + enum { isStdFundamental = isStdArith || isStdFloat || isVoid }; + + enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt::value }; + enum { isSignedInt = isStdSignedInt || IsCustomSignedInt::value }; + enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; + enum { isFloat = isStdFloat || IsCustomFloat::value }; + enum { isArith = isIntegral || isFloat }; + enum { isFundamental = isStdFundamental || isArith || isFloat }; + enum { + isConst = + sizeof(is_const(Wrap())) == sizeof(Private::YES) + }; + + enum { + isVolatile = + sizeof(is_volatile(Wrap())) == sizeof(Private::YES) + }; + enum { isScalar = isStdArith /* || isPointer */ /* || isMemberPointer */ }; + private: + typedef typename Private::AdjReference:: + template In::Result AdjType; + + public: + + + 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) +// Oct 05, 2002: ported by Benjamin Kaufmann to MSVC 6 +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPETRAITS_INC_ \ No newline at end of file diff --git a/MSVC/1200/Typelist.h b/MSVC/1200/Typelist.h new file mode 100644 index 0000000..5d949d7 --- /dev/null +++ b/MSVC/1200/Typelist.h @@ -0,0 +1,1146 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Sept 29, 2002 +// +// Rani Sharoni's VC 7 port is heavily based on explicit template specialization +// inside class templates. +// This approach has two problems: +// First: It does not seem to work correctly with VC 6 +// Second: The C++ Standard allows explicit specialization only in namespace-scope. +// +// In general my solutions need more template-classes. But I hope that they +// are all conforming to the C++ Standard. + + +#ifndef TYPELIST_INC_ +#define TYPELIST_INC_ + +#include "Nulltype.h" +#include "TypeManip.h" +#include "static_check.h" + +#define ASSERT_TYPELIST(TList) \ +typedef ::Loki::Private::static_assert_test::value ) >)> static_assert_typedef_ + +//////////////////////////////////////////////////////////////////////////////// +// macros TYPELIST_1, TYPELIST_2, ... TYPELIST_50 +// Each takes a number of arguments equal to its numeric suffix +// The arguments are type names. TYPELIST_NN generates a typelist containing +// all types passed as arguments, in that order. +// Example: TYPELIST_2(char, int) generates a type containing char and int. +//////////////////////////////////////////////////////////////////////////////// + +#define TYPELIST_1(T1) ::Loki::Typelist + +#define TYPELIST_2(T1, T2) ::Loki::Typelist + +#define TYPELIST_3(T1, T2, T3) ::Loki::Typelist + +#define TYPELIST_4(T1, T2, T3, T4) \ + ::Loki::Typelist + +#define TYPELIST_5(T1, T2, T3, T4, T5) \ + ::Loki::Typelist + +#define TYPELIST_6(T1, T2, T3, T4, T5, T6) \ + ::Loki::Typelist + +#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ + ::Loki::Typelist + +#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ + ::Loki::Typelist + +#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ + ::Loki::Typelist + +#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ + ::Loki::Typelist + +#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \ + ::Loki::Typelist + +#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \ + ::Loki::Typelist + +#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \ + ::Loki::Typelist + +#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14) \ + ::Loki::Typelist + +#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15) \ + ::Loki::Typelist + +#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16) \ + ::Loki::Typelist + +#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17) \ + ::Loki::Typelist + +#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18) \ + ::Loki::Typelist + +#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19) \ + ::Loki::Typelist + +#define TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \ + ::Loki::Typelist + +#define TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \ + ::Loki::Typelist + +#define TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \ + ::Loki::Typelist + +#define TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \ + ::Loki::Typelist + +#define TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \ + ::Loki::Typelist + +#define TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \ + ::Loki::Typelist + +#define TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26) \ + ::Loki::Typelist + +#define TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27) \ + ::Loki::Typelist + +#define TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28) \ + ::Loki::Typelist + +#define TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29) \ + ::Loki::Typelist + +#define TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \ + ::Loki::Typelist + +#define TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \ + ::Loki::Typelist + +#define TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \ + ::Loki::Typelist + +#define TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \ + ::Loki::Typelist + +#define TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \ + ::Loki::Typelist + +#define TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35) \ + ::Loki::Typelist + +#define TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36) \ + ::Loki::Typelist + +#define TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37) \ + ::Loki::Typelist + +#define TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38) \ + ::Loki::Typelist + +#define TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39) \ + ::Loki::Typelist + +#define TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \ + ::Loki::Typelist + +#define TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \ + ::Loki::Typelist + +#define TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \ + ::Loki::Typelist + +#define TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \ + ::Loki::Typelist + +#define TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \ + ::Loki::Typelist + +#define TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45) \ + ::Loki::Typelist + +#define TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46) \ + ::Loki::Typelist + +#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47) \ + ::Loki::Typelist + +#define TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48) \ + ::Loki::Typelist + +#define TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49) \ + ::Loki::Typelist + +#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \ + ::Loki::Typelist + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template Typelist +// The building block of typelists of any length +// Use it through the TYPELIST_NN macros +// Defines nested types: +// Head (first element, a non-typelist type by convention) +// Tail (second element, can be another typelist) +//////////////////////////////////////////////////////////////////////////////// + template + struct Typelist + { + typedef T Head; + typedef U Tail; + }; + + namespace TL + { + + namespace Private + { + template struct TList_is_not_legal_Typelist; + + template <> struct TList_is_not_legal_Typelist{}; + + struct Typelist_tag {}; + struct NullType_tag {}; + struct NoneList_tag {}; + + enum + { + NoneList_ID = 0, + Typelist_ID = 1, + AtomList_ID = 2, + NullType_ID = 4 + + }; +//////////////////////////////////////////////////////////////////////////////// +// class template IsTypelist +// detects if type is Typelist (including Nulltype) +// Invocation : +// IsTypelist::value +//////////////////////////////////////////////////////////////////////////////// + template + struct IsTypelist + { + private: + typedef TypeTag<1>::X List; + typedef TypeTag<2>::X AtomList; + typedef TypeTag<3>::X NullList; + typedef TypeTag<4>::X NoList; + + // VC 6.0 does not allow overloads + // for check(Type2Type< Typelist >) + // and check(Type2Type); + // so we must use to different functions + template + static TypeTag<1>::X check(Type2Type< Typelist >); + static TypeTag<4>::X check(...); + + template + static TypeTag<2>::X check2(Type2Type< Typelist >); + static TypeTag<4>::X check2(...); + + static TypeTag<3>::X check3(Type2Type); + static TypeTag<4>::X check3(...); + + + public: + enum + { + temp1 = sizeof(check(Type2Type())) == sizeof(TypeTag<1>::X) ? Typelist_ID : NoneList_ID, + temp2 = sizeof(check2(Type2Type())) == sizeof(TypeTag<2>::X) ? AtomList_ID : NoneList_ID, + temp4 = temp2 ? Typelist_ID :NoneList_ID, + temp3 = sizeof(check3(Type2Type())) == sizeof(TypeTag<3>::X) ? NullType_ID : NoneList_ID, + value = temp1 || temp2 || temp3, + type_id = (temp1 ^ temp4) | temp2 | temp3 + }; + typedef typename Select + < + type_id == Typelist_ID || type_id == AtomList_ID, + Typelist_tag, + typename Select::Result + > + ::Result type_tag; + + + + }; + + } // end of namespace Private +//////////////////////////////////////////////////////////////////////////////// +// class template MakeTypelist +// Takes a number of arguments equal to its numeric suffix +// The arguments are type names. +// MakeTypeList::Result +// returns a typelist that is of T1, T2, ... +//////////////////////////////////////////////////////////////////////////////// +// MakeTypeList-Template from Rani Sharoni's VC 7 port. + template + < typename T1 = NullType, typename T2 = NullType, typename T3 = NullType, + typename T4 = NullType, typename T5 = NullType, typename T6 = NullType, + typename T7 = NullType, typename T8 = NullType, typename T9 = NullType, + typename T10 = NullType, typename T11 = NullType, typename T12 = NullType, + typename T13 = NullType, typename T14 = NullType, typename T15 = NullType, + typename T16 = NullType, typename T17 = NullType, typename T18 = NullType + > + struct MakeTypeList + { + private: + typedef typename MakeTypeList + < + T2 , T3 , T4 , + T5 , T6 , T7 , + T8 , T9 , T10, + T11, T12, T13, + T14, T15, T16, + T17, T18 + > + ::Result TailResult; + + public: + typedef Typelist Result; + }; + + template<> + struct MakeTypeList + < + NullType, NullType, NullType, + NullType, NullType, NullType, + NullType, NullType, NullType, + NullType, NullType, NullType, + NullType, NullType, NullType, + NullType, NullType, NullType + > + { + typedef NullType Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Length +// Computes the length of a typelist +// Invocation (TList is a typelist): +// Length::value +// returns a compile-time constant containing the length of TList, not counting +// the end terminator (which by convention is NullType) +//////////////////////////////////////////////////////////////////////////////// + template + struct Length + { + private: + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + public: + + enum {value = 1 + Length::value}; + }; + + // explicit specialization for an empty list. + // this is the border case for the recursive length-calculation + template <> + struct Length + { + enum {value = 0}; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAt +// Finds the type at a given index in a typelist +// Invocation (TList is a typelist and index is a compile-time integral +// constant): +// TypeAt::Result +// returns the type in position 'index' in TList +// If you pass an out-of-bounds index, the result is a compile-time error +//////////////////////////////////////////////////////////////////////////////// +namespace Private +{ + // The type at Index i is the type at i-1 of the List's Tail + template + struct TypeAtImpl + { + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename TypeAtImpl::template In::Result Result; + }; + + }; + // the border case is represented by an explicit specialization + // The type at Index 0 is the type of the head. + template <> + struct TypeAtImpl<0> + { + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef Head Result; + }; + }; +} // end of namespace Private + + template + struct TypeAt + { + typedef typename Private::TypeAtImpl::template In::Result Result ; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAtNonStrict +// Finds the type at a given index in a typelist +// Invocations (TList is a typelist and index is a compile-time integral +// constant): +// a) TypeAt::Result +// returns the type in position 'index' in TList, or NullType if index is +// out-of-bounds +// b) TypeAt::Result +// returns the type in position 'index' in TList, or D if index is out-of-bounds +//////////////////////////////////////////////////////////////////////////////// + template + struct TypeAtNonStrict; +namespace Private +{ + // if TList is not NullType, check if Index is 0. + // if Index is 0, the result is TList::Head + // if Index is > 0, the result is the result of appliying TypeAtNonStrict + // to the list's and Index-1 + template + struct TypeAtNonStrictImpl + { + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename Select + < + Index == 0, // The condition + typename TList::Head, // true-case + typename TypeAtNonStrict::Result + >::Result Result; + }; + }; + + // if TList is NullType the result is *always* the specified DefaultType. + template <> + struct TypeAtNonStrictImpl + { + template + struct In + { + typedef DefType Result; + }; + }; + +} // end of namespace Private + template + struct TypeAtNonStrict + { + typedef typename + Private::TypeAtNonStrictImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template IndexOf +// Finds the index of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// IndexOf::value +// returns the position of T in TList, or -1 if T is not found in TList +//////////////////////////////////////////////////////////////////////////////// + template + struct IndexOf; +namespace Private +{ + // If TList is a typelist and TList::Head is T, then the Index is 0 + // If TList::Head is not T, compute the result of IndexOf applied to + // TList's tail and T into a temporary value temp. + // If temp is -1, then value is -1 + // Else value is 1 + temp + template + struct IndexOfImpl + { + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + private: + enum {temp = IsEqualType::value != 0 ? 0 + : IndexOf::temp}; + + public: + enum {value = temp == -1 ? -1 : 1 + temp}; + }; + }; + + // T cannot be in an empty list. + // Therefore return -1 to indicate Not-In-List + template <> + struct IndexOfImpl + { + template + struct In + { + enum {value = -1}; + }; + }; + +} // end of namespace Private + + // The primary IndexOfImpl-Template is always one step ahead. + // Therefore if T is in list, we need to subtract one from the result. + template + struct IndexOf + { + enum {temp = Private::IndexOfImpl::template In::value}; + enum {value = temp == -1 ? -1 : temp - 1}; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template Append +// Appends a type or a typelist to another +// Invocation (TList is a typelist and T is either a type or a typelist): +// Append::Result +// returns a typelist that is TList followed by T and NullType-terminated +//////////////////////////////////////////////////////////////////////////////// + template + struct Append; + +namespace Private +{ + template + struct AppendImpl + { // if TList is not NullType the result + // is a typelist having TList::Head as its Head and + // and the result of appending T to TList::Tail as its tail. + ASSERT_TYPELIST(TList); + template + struct In + { + typedef Typelist::Result> Result; + }; + + }; + + template <> + struct AppendImpl + { // if TList is NullType, check if T is NullType, a single type + // or a typelist + // If TList is NullType and T is NullType + // the result is NullType, too + // + // If TList is NullType and T is not NullType. + // Check if T is a Typelist + // + // if TList is NullType and T is a typelist the result is T + // if TList is NullType and T is not a typelist + // the result is a typelist containing only T + template + struct In + { + typedef typename Select + < + IsEqualType::value, // is T == Nulltype? + NullType, // yes + typename Select // no. check if T is a Typelist + < + IsTypelist::value, // is T a typelist? + T, // yes + Typelist // no + >::Result + >::Result Result; + }; + }; + +} // end of namespace Private + + template + struct Append + { + typedef typename Private::AppendImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Erase +// Erases the first occurence, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// Erase::Result +// returns a typelist that is TList without the first occurence of T +//////////////////////////////////////////////////////////////////////////////// + template + struct Erase; +namespace Private +{ + template + struct EraseImpl + { // TList is not NullType. + // Check if TList::Head is equal to T + // if T is the same as TList::Head, then the Result is TList::Tail + // + // if TList is not NullType and TList::Head is not equal to T, + // then the Result is a Typelist having TList::Head as its Head + // and the result of applying Erase to the tail of list as its + // tail. + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename Select + < + IsEqualType::value, // is T equal to Head? + Tail, // Yes. Result is tail + Typelist::Result> + >::Result Result; + + }; + }; + + // if TList is NullType the result is NullType. + template <> + struct EraseImpl + { + template + struct In + { + typedef NullType Result; + }; + }; +} // end of namespace Private + + template + struct Erase + { + typedef typename Private::EraseImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template EraseAll +// Erases all occurences, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// EraseAll::Result +// returns a typelist that is TList without any occurence of T +//////////////////////////////////////////////////////////////////////////////// + template + struct EraseAll; +namespace Private +{ + template + struct EraseAllImpl + { // TList is not NullType. + // Check if TList::Head is equal to T + // If T is equal to TLIst::Head the result is the result of EraseAll + // applied to TList::Tail + // + // If T is not equal to TList::Head the result is a Typelist with + // TList::Head as its head and the result of applying EraseAll to TList::Tail + // as its tail. + template + struct In + { + ASSERT_TYPELIST(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename Select + < + IsEqualType::value, // is T == Head? + typename EraseAll::Result, // Yes + Typelist::Result> + >::Result Result; + }; + }; + + // if TList is NullType the result is NullType. + template <> + struct EraseAllImpl + { + template + struct In + { + typedef NullType Result; + }; + }; +} // end of namespace Private + + template + struct EraseAll + { + typedef typename Private::EraseAllImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDuplicates +// Removes all duplicate types in a typelist +// Invocation (TList is a typelist): +// NoDuplicates::Result +//////////////////////////////////////////////////////////////////////////////// +// NoDuplicates taken from Rani Sharoni's Loki VC7-Port. + template + struct NoDuplicates + { + private: + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + ASSERT_TYPELIST(TList); + + typedef typename NoDuplicates::Result L1; + typedef typename Erase::Result L2; + + public: + typedef Typelist Result; + }; + + template <> + struct NoDuplicates + { + typedef NullType Result; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template Replace +// Replaces the first occurence of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which the first occurence of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + template + struct Replace; +namespace Private +{ + // If TList is not NullType, check if T is equal to TList::Head + template + struct ReplaceImpl + { + template + struct In + { + // If TList::Head is equal to T, the result is a typelist + // with U as its head an TList::Tail as its tail. + // If T is not equal to TList::Head, the result is a typelist + // with TList::Head as its head and the result of applying + // Replace to TList::Tail, T, U as its tail + ASSERT_VALID(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename Select + < + IsEqualType::value, // Is T == Head? + Typelist, // yes + Typelist::Result> + >::Result Result; + }; + }; + + // If TList is NullType the result is NullType + template <> + struct ReplaceImpl + { + template + struct In + { + typedef NullType Result; + }; + }; +} // end of namespace Private + + template + struct Replace + { + typedef typename + Private::ReplaceImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ReplaceAll +// Replaces all occurences of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which all occurences of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + template + struct ReplaceAll; + +namespace Private +{ + // If TList is not NullType, check if T is equal to TList::Head + template + struct ReplaceAllImpl + { + template + struct In + { + ASSERT_VALID(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename Select + < + IsEqualType::value, // Is T == Head? + Typelist::Result>, // yes + Typelist::Result> + >::Result Result; + }; + }; + + // If TList is NullType the result is NullType + template <> + struct ReplaceAllImpl + { + template + struct In + { + typedef NullType Result; + }; + }; +} + template + struct ReplaceAll + { + typedef typename + Private::ReplaceAllImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Reverse +// Reverses a typelist +// Invocation (TList is a typelist): +// Reverse::Result +// returns a typelist that is TList reversed +//////////////////////////////////////////////////////////////////////////////// +// Reverse taken from Rani Sharoni's Loki VC7-Port. + template struct Reverse; + + template <> + struct Reverse + { + typedef NullType Result; + }; + + template + struct Reverse + { + private: + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + ASSERT_TYPELIST(TList); + + public: + typedef typename Append< + typename Reverse::Result, Head>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template MostDerived +// Finds the type in a typelist that is the most derived from a given type +// Invocation (TList is a typelist, T is a type): +// MostDerived::Result +// returns the type in TList that's the most derived from T +//////////////////////////////////////////////////////////////////////////////// + template struct MostDerived; +namespace Private +{ + template + struct MostDerivedImpl + { + template + struct In + { + private: + ASSERT_VALID(TList); + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + typedef typename MostDerived::Result Candidate; + public: + typedef typename Select + < + SUPERSUBCLASS(Candidate, Head), + Head, + Candidate + >::Result Result; + }; + }; + template <> + struct MostDerivedImpl + { + template + struct In {typedef T Result;}; + }; +} // end of namespace Private + + template + struct MostDerived + { + typedef typename + Private::MostDerivedImpl::template In::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DerivedToFront +// Arranges the types in a typelist so that the most derived types appear first +// Invocation (TList is a typelist): +// DerivedToFront::Result +// returns the reordered TList +//////////////////////////////////////////////////////////////////////////////// +// DerivedToFront taken from Rani Sharoni's Loki VC7-Port. + template + struct DerivedToFront + { + private: + ASSERT_TYPELIST(TList); + + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + typedef typename MostDerived::Result TheMostDerived; + typedef typename ReplaceAll::Result Temp; + typedef typename DerivedToFront::Result L; + + public: + typedef Typelist Result; + }; + + template <> + struct DerivedToFront + { + typedef NullType Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DerivedToFrontAll +// Arranges all the types in a typelist so that the most derived types appear first +// Invocation (TList is a typelist): +// DerivedToFront::Result +// returns the reordered TList +//////////////////////////////////////////////////////////////////////////////// +// DerivedToFrontAll taken from Rani Sharoni's Loki VC7-Port. + template + struct DerivedToFrontAll + { + private: + ASSERT_TYPELIST(TList); + + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + typedef typename MostDerived::Result TheMostDerived; + typedef typename Replace::Result L; + + typedef typename DerivedToFrontAll::Result TailResult; + + public: + typedef Typelist Result; + }; + + template <> + struct DerivedToFrontAll + { + typedef NullType Result; + }; + + + } // end of namespace TL +} // end of namespace Loki +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27 +// (credit due to Dave Taylor) +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +// Sept 29, 2002: ported by Benjamin Kaufmann to MSVC 6.0 +//////////////////////////////////////////////////////////////////////////////// +#endif // TYPELIST_INC_ \ No newline at end of file diff --git a/MSVC/1200/Visitor.h b/MSVC/1200/Visitor.h new file mode 100644 index 0000000..fc8a056 --- /dev/null +++ b/MSVC/1200/Visitor.h @@ -0,0 +1,556 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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: Oct 27, 2002 +// +// 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 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, +// public Visitor +// { +// public: +// void Visit(RasterBitmap&); // visit a RasterBitmap +// void Visit(Paragraph &); // visit a Paragraph +// }; +//////////////////////////////////////////////////////////////////////////////// +namespace Private +{ + // helper for Visitor's the left base class + template + struct VisitorImplLeft + { + template + struct In + { + typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + // helper for Visitor's the right base class + template + struct VisitorImplRight + { + template + struct In + { + typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + // simulates specialization + // class Visitor + template <> + struct VisitorImplLeft + { + template + struct In + { + struct Result + { + typedef R ReturnType; + virtual ReturnType Visit(T&) = 0; + }; + }; + }; + + // simulates the left base class for the specialization + // class Visitor, R> + template <> + struct VisitorImplLeft + { + template + struct In + { + typedef Visitor Result; + }; + }; + + template <> + struct VisitorImplRight + { + template + struct In + { + struct Result {}; + }; + }; + + // simulates the right base class for the specialization + // class Visitor, R> + template <> + struct VisitorImplRight + { + template + struct In + { + typedef Visitor Result; + }; + }; + + template <> + struct VisitorImplRight + { + template + struct In + { + struct Result {}; + }; + }; + + // MSVC 6.0 will complain if we try to let Visitor inherit + // directly from VisitorImplLeft/VisitorImplRight + template + struct VisitorImplLeftWrap + { + struct Dummy{}; + typedef typename VisitorImplLeft + < + TL::Private::IsTypelist::type_id == TL::Private::AtomList_ID ? + TL::Private::Typelist_ID : + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + template + struct VisitorImplRightWrap + { + struct Dummy{}; + typedef typename VisitorImplRight + < + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + +} + template + class Visitor : public Private::VisitorImplLeftWrap::Result, + public Private::VisitorImplRightWrap::Result + + { + public: + typedef R ReturnType; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitorImpl +// Implements non-strict visitation (you can implement only part of the Visit +// functions) +//////////////////////////////////////////////////////////////////////////////// + + template class BaseVisitorImpl; + + // class for the void-case + template class BaseVisitorImplVoid; + +namespace Private +{ + template + struct BaseVisitorImplHelper + { + template + struct In + { + typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + template<> + struct BaseVisitorImplHelper + { + template + struct In + { + typedef BaseVisitorImpl Result; + }; + }; + + template<> + struct BaseVisitorImplHelper + { + template + struct In + { + struct Result {}; + }; + }; + + template + struct BaseVisitorImplWrap + { + struct Dummy {}; + typedef typename BaseVisitorImplHelper + < + TL::Private::IsTypelist:: + type_id == TL::Private::AtomList_ID ? + TL::Private::Typelist_ID : + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + template + struct BaseVisitorImplVoidHelper + { + template + struct In + { + typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + template<> + struct BaseVisitorImplVoidHelper + { + template + struct In + { + typedef BaseVisitorImplVoid Result; + }; + }; + + template<> + struct BaseVisitorImplVoidHelper + { + template + struct In + { + struct Result {}; + }; + }; + + template + struct BaseVisitorImplVoidWrap + { + struct Dummy {}; + typedef typename BaseVisitorImplVoidHelper + < + TL::Private::IsTypelist:: + type_id == TL::Private::AtomList_ID ? + TL::Private::Typelist_ID : + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; +} + + template + class BaseVisitorImpl : public Visitor, + public Private::BaseVisitorImplWrap::Result + { + ASSERT_TYPELIST(TList); + + public: + // using BaseVisitorImpl::Visit; + + virtual R Visit(typename TList::Head&) + { return R(); } + }; + + // class for the void-case + template + class BaseVisitorImplVoid : public Visitor, + public Private::BaseVisitorImplVoidWrap::Result + { + ASSERT_TYPELIST(TList); + + public: + // using BaseVisitorImpl::Visit; + + virtual void Visit(typename TList::Head&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultCatchAll +//////////////////////////////////////////////////////////////////////////////// + +template +struct DefaultCatchAll +{ + static R OnUnknownVisitor(Visited&, BaseVisitor&) + { return R(); } +}; + +// template template parameter workaround. +// use Wrapper-Classes like this to instantiate BaseVisitable +struct DefaultCatchAllWrapper +{ + template + struct In + { + typedef DefaultCatchAll type; + }; +}; + +template +struct DefaultCatchAllVoid +{ + static R OnUnknownVisitor(Visited&, BaseVisitor&) + {} +}; + +struct DefaultCatchAllVoidWrapper +{ + template + struct In + { + typedef DefaultCatchAllVoid type; + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template NonStrictVisitor +// Implements non-strict visitation (you can implement only part of the Visit +// functions) +//////////////////////////////////////////////////////////////////////////////// + + template + struct NonStrictVisitorUnit : public Base + { + typedef typename Base::ReturnType ReturnType; + ReturnType Visit(T&) + { + return ReturnType(); + } + }; + + struct NonStrictVisitorUnitWrapper + { + template + struct In + { + typedef NonStrictVisitorUnit type; + }; + }; + + + template + class NonStrictVisitor + : public GenLinearHierarchy< + TList, + NonStrictVisitorUnitWrapper, + Visitor > + { + }; + + template + struct NonStrictVisitorUnitVoid : public Base + { + typedef void ReturnType; + ReturnType Visit(T&) + { + } + }; + + struct NonStrictVisitorUnitVoidWrapper + { + template + struct In + { + typedef NonStrictVisitorUnitVoid type; + }; + }; + + + template + class NonStrictVisitorVoid + : public GenLinearHierarchy< + TList, + NonStrictVisitorUnitWrapper, + Visitor > + { + }; +//////////////////////////////////////////////////////////////////////////////// +// 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 + static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) + { + typedef ApplyInnerType2::type CatchA; + // Apply the Acyclic Visitor + if (Visitor* p = dynamic_cast*>(&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 + static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) + { + typedef ApplyInnerType2::type CatchA; + // Apply the Acyclic Visitor + if (Visitor* p = dynamic_cast*>(&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 +//////////////////////////////////////////////////////////////////////////////// + +#define DEFINE_VISITABLE() \ + virtual ReturnType Accept(BaseVisitor& guest) \ + { return AcceptImpl(*this, guest); } + +#define DEFINE_VISITABLE_VOID() \ + virtual void Accept(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 +//////////////////////////////////////////////////////////////////////////////// + template + class CyclicVisitor : public Visitor + { + public: + typedef R ReturnType; + // using Visitor::Visit; + + template + ReturnType GenericVisit(Visited& host) + { + Visitor& subObj = *this; + return subObj.Visit(host); + } + }; + + template + class CyclicVisitorVoid : public Visitor + { + public: + typedef void ReturnType; + // using Visitor::Visit; + + template + ReturnType GenericVisit(Visited& host) + { + Visitor& 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 +//////////////////////////////////////////////////////////////////////////////// + +#endif // VISITOR_INC_ + diff --git a/MSVC/1200/static_check.h b/MSVC/1200/static_check.h new file mode 100644 index 0000000..43180e1 --- /dev/null +++ b/MSVC/1200/static_check.h @@ -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 struct CompileTimeError; + template<> struct CompileTimeError {}; + + namespace Private + { + template struct static_assert_test{}; + template struct SizeError; + + template <> struct SizeError{}; + } +} + +#define STATIC_SIZE_ASSERT(Type, ExpSize) \ +typedef ::Loki::Private::static_assert_test)> 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_