diff --git a/MSVC/1300/AbstractFactory.h b/MSVC/1300/AbstractFactory.h new file mode 100644 index 0000000..55dce96 --- /dev/null +++ b/MSVC/1300/AbstractFactory.h @@ -0,0 +1,165 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef ABSTRACTFACTORY_INC_ +#define ABSTRACTFACTORY_INC_ + +#include "Typelist.h" +#include "TypeManip.h" +#include "HierarchyGenerators.h" + +#include + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template AbstractFactoryUnit +// The building block of an Abstract Factory +//////////////////////////////////////////////////////////////////////////////// + + template + class AbstractFactoryUnit + { + public: + virtual T* DoCreate(Type2Type) = 0; + virtual ~AbstractFactoryUnit() {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template AbstractFactory +// Defines an Abstract Factory interface starting from a typelist +//////////////////////////////////////////////////////////////////////////////// + + template + < + class TList, + template class Unit = AbstractFactoryUnit + > + class AbstractFactory : public GenScatterHierarchy + { + public: + typedef TList ProductList; + + template T* Create() + { + Unit& 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; + ConcreteProduct* DoCreate(Type2Type) + { + return new ConcreteProduct; + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template PrototypeFactoryUnit +// Creates an object by cloning a prototype +// There is a difference between the implementation herein and the one described +// in the book: GetPrototype and SetPrototype use the helper friend +// functions DoGetPrototype and DoSetPrototype. The friend functions avoid +// name hiding issues. Plus, GetPrototype takes a reference to pointer +// instead of returning the pointer by value. +//////////////////////////////////////////////////////////////////////////////// + + template + class 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_); + return pPrototype_->Clone(); + } + + private: + AbstractProduct* pPrototype_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ConcreteFactory +// Implements an AbstractFactory interface +//////////////////////////////////////////////////////////////////////////////// + + template + < + class AbstractFact, + template class Creator = OpNewFactoryUnit, + class TList = typename 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!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // ABSTRACTFACTORY_INC_ diff --git a/MSVC/1300/AssocVector.h b/MSVC/1300/AssocVector.h new file mode 100644 index 0000000..b49c3b9 --- /dev/null +++ b/MSVC/1300/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() || this->operator()(val.first, i->first)) + { + i = Base::insert(i, val); + found = false; + } + return std::make_pair(i, !found); + } + + iterator insert(iterator pos, const value_type& val) + { + if (pos != end() && this->operator()(*pos, val) && + (pos == end() - 1 || + !this->operator()(val, pos[1]) && + this->operator()(pos[1], val))) + { + return Base::insert(pos, val); + } + return insert(val).first; + } + + template + void insert(InputIterator first, InputIterator last) + { for (; first != last; ++first) insert(*first); } + + void erase(iterator pos) + { Base::erase(pos); } + + size_type erase(const key_type& k) + { + iterator i(find(k)); + if (i == end()) return 0; + erase(i); + return 1; + } + + void erase(iterator first, iterator last) + { Base::erase(first, last); } + + void swap(AssocVector& other) + { + using std::swap; + Base::swap(other); + MyCompare& me = *this; + MyCompare& rhs = other; + swap(me, rhs); + } + + void clear() + { Base::clear(); } + + // observers: + key_compare key_comp() const + { return *this; } + + value_compare value_comp() const + { + const key_compare& comp = *this; + return value_compare(comp); + } + + // 23.3.1.3 map operations: + iterator find(const key_type& k) + { + iterator i(lower_bound(k)); + if (i != end() && this->operator()(k, i->first)) + { + i = end(); + } + return i; + } + + const_iterator find(const key_type& k) const + { + const_iterator i(lower_bound(k)); + if (i != end() && this->operator()(k, i->first)) + { + i = end(); + } + return i; + } + + size_type count(const key_type& k) const + { return find(k) != end(); } + + iterator lower_bound(const key_type& k) + { + MyCompare& me = *this; + return std::lower_bound(begin(), end(), k, me); + } + + const_iterator lower_bound(const key_type& k) const + { + const MyCompare& me = *this; + return std::lower_bound(begin(), end(), k, me); + } + + iterator upper_bound(const key_type& k) + { + MyCompare& me = *this; + return std::upper_bound(begin(), end(), k, me); + } + + const_iterator upper_bound(const key_type& k) const + { + const MyCompare& me = *this; + return std::upper_bound(begin(), end(), k, me); + } + + std::pair 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/1300/EmptyType.h b/MSVC/1300/EmptyType.h new file mode 100644 index 0000000..5227ba8 --- /dev/null +++ b/MSVC/1300/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/1300/Factory.h b/MSVC/1300/Factory.h new file mode 100644 index 0000000..62bb4dc --- /dev/null +++ b/MSVC/1300/Factory.h @@ -0,0 +1,143 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef FACTORY_INC_ +#define FACTORY_INC_ + +#include "LokiTypeInfo.h" +#include "AssocVector.h" +#include + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultFactoryError +// Manages the "Unknown Type" error in an object factory +//////////////////////////////////////////////////////////////////////////////// + + template + struct DefaultFactoryError + { + struct Exception : public std::exception + { + const char* what() const throw() { return "Unknown Type"; } + }; + + static AbstractProduct* OnUnknownType(IdentifierType) + { + throw Exception(); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Factory +// Implements a generic object factory +//////////////////////////////////////////////////////////////////////////////// + + template + < + class AbstractProduct, + typename IdentifierType, + typename ProductCreator = AbstractProduct* (*)(), + template + 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*), + template + 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(typeid(*model)); + } + + 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 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // FACTORY_INC_ diff --git a/MSVC/1300/Functor.h b/MSVC/1300/Functor.h new file mode 100644 index 0000000..c211881 --- /dev/null +++ b/MSVC/1300/Functor.h @@ -0,0 +1,1347 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef FUNCTOR_INC_ +#define FUNCTOR_INC_ + +#include "Typelist.h" +#include "EmptyType.h" +#include "SmallObj.h" +#include "TypeTraits.h" +#include +#include + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl (internal) +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + + template class ThreadingModel> + struct FunctorImplBase : public SmallObject + { + typedef R ResultType; + + 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; + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// macro DEFINE_CLONE_FUNCTORIMPL +// Implements the DoClone function for a functor implementation +//////////////////////////////////////////////////////////////////////////////// + +#define DEFINE_CLONE_FUNCTORIMPL(Cls) \ + virtual Cls* 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 ThreadingModel> + class In : public Private::FunctorImplBase + { + public: + typedef R ResultType; + virtual R operator()() = 0; + }; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 1 parameter +//////////////////////////////////////////////////////////////////////////////// + + template <> + struct FunctorImplHelper<1> + { + template class ThreadingModel> + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + + public: + typedef R ResultType; + typedef typename TypeTraits::ParameterType Parm1; + virtual R operator()(Parm1) = 0; + }; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 2 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<2> + { + template class ThreadingModel> + class In : public Private::FunctorImplBase + { + typedef typename TL::TypeAt::Result P1; + typedef typename TL::TypeAt::Result P2; + + public: + typedef R ResultType; + typedef typename TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + virtual R operator()(Parm1, Parm2) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 3 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<3> + { + template class ThreadingModel> + 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 TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + virtual R operator()(Parm1, Parm2, Parm3) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 4 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<4> + { + template class ThreadingModel> + 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 TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 5 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<5> + { + template class ThreadingModel> + 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 TypeTraits::ParameterType Parm1; + typedef typename TypeTraits::ParameterType Parm2; + typedef typename TypeTraits::ParameterType Parm3; + typedef typename TypeTraits::ParameterType Parm4; + typedef typename TypeTraits::ParameterType Parm5; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 6 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<6> + { + template class ThreadingModel> + 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 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 R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 7 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<7> + { + template class ThreadingModel> + 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 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 R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 8 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<8> + { + template class ThreadingModel> + 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 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 R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 9 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<9> + { + template class ThreadingModel> + 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 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 R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, Parm7, Parm8, Parm9) = 0; + }; + }; +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImplHelper +// Specialization for 10 parameters +//////////////////////////////////////////////////////////////////////////////// + template <> + struct FunctorImplHelper<10> + { + template class ThreadingModel> + 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 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 R 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 ThreadingModel> + 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 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 R 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 ThreadingModel> + 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 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 R 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 ThreadingModel> + 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 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 R 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 ThreadingModel> + 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 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 R 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 ThreadingModel> + 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 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 R 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, + template class ThreadingModel = DEFAULT_THREADING + > + class FunctorImpl + : public Private::FunctorImplHelper + < + TL::Length::value + > + ::template In + { + ASSERT_TYPELIST(TList); + }; + +//////////////////////////////////////////////////////////////////////////////// +// 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::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; + + FunctorHandler(const Fun& fun) : f_(fun) {} + + DEFINE_CLONE_FUNCTORIMPL(FunctorHandler) + + // operator() implementations for up to 15 arguments + + ResultType operator()() + { return f_(); } + + ResultType operator()(Parm1 p1) + { return f_(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f_(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f_(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f_(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f_(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f_(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return f_(p1, p2, p3, p4, p5, p6, p7); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + ResultType 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_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + + ResultType 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_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + + ResultType 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_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + + ResultType 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_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + ResultType 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 f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15); + } + + private: + Fun f_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// 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::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; + + MemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn) + : pObj_(pObj), pMemFn_(pMemFn) + {} + + DEFINE_CLONE_FUNCTORIMPL(MemFunHandler) + + ResultType operator()() + { return ((*pObj_).*pMemFn_)(); } + + ResultType operator()(Parm1 p1) + { return ((*pObj_).*pMemFn_)(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return ((*pObj_).*pMemFn_)(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return ((*pObj_).*pMemFn_)(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11); + } + + ResultType 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 ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12); + } + + ResultType 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 ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13); + } + + ResultType 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 ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14); + } + + ResultType 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 ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15); + } + + private: + PointerToObj pObj_; + PointerToMemFn pMemFn_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Functor +// A generalized functor implementation with value semantics +//////////////////////////////////////////////////////////////////////////////// + + template class ThreadingModel = DEFAULT_THREADING> + class Functor + { + public: + // Handy type definitions for the body type + typedef FunctorImpl Impl; + typedef R ResultType; + typedef TList ParmList; + + template + struct RebindParmList + { + typedef Functor Result; + }; + + 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; + + // Member functions + + Functor() : spImpl_() + {} + + +#if 0 // The Helper class will do those constructions because of VC7 bug + Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())) + {} +#endif + + Functor(std::auto_ptr spImpl) : spImpl_(spImpl) + {} + + template + Functor(Fun fun) + : spImpl_(new FunctorHandler(fun)) + {} + + template + Functor(const PtrObj& p, MemFn memFn) + : spImpl_(new MemFunHandler(p, memFn)) + {} + + Functor& operator=(const Functor& rhs) + { + Functor copy(rhs); + // swap auto_ptrs by hand + Impl* p = spImpl_.spImpl_.release(); + spImpl_.spImpl_.reset(copy.spImpl_.spImpl_.release()); + copy.spImpl_.spImpl_.reset(p); + return *this; + } + + ResultType operator()() + { return (*spImpl_)(); } + + ResultType operator()(Parm1 p1) + { return (*spImpl_)(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return (*spImpl_)(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return (*spImpl_)(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return (*spImpl_)(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return (*spImpl_)(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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: + + // VC7 can't see the defined ctor when the template version in present + struct Helper + { + Helper() + : spImpl_(0) + {} + + Helper(const Helper &rhs) + : spImpl_(Impl::Clone(rhs.spImpl_.get())) + {} + + explicit Helper(std::auto_ptr spImpl) + : spImpl_(spImpl) + {} + + template + explicit Helper(U *ptr) + : spImpl_(ptr) + {} + + Impl& operator*() const + { + return *spImpl_; + } + + public: + std::auto_ptr spImpl_; + }; + + Helper 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 TList::Tail ParmList; + + typedef typename Fctor::template RebindParmList + < + typename Fctor::ResultType, + ParmList + > + ::Result 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 OriginalFunctor::ResultType ResultType; + + 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 + + ResultType operator()() + { return f_(b_); } + + ResultType operator()(Parm1 p1) + { return f_(b_, p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f_(b_, p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f_(b_, p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f_(b_, p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f_(b_, p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f_(b_, p1, p2, p3, p4, p5, p6); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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); } + + ResultType 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; + + // + // VC7 don't support the auto_ptr tricks + // + std::auto_ptr apParam + ( + new BinderFirst(fun, bound) + ); + + return Outgoing(apParam); + } + +//////////////////////////////////////////////////////////////////////////////// +// 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::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 + + ResultType operator()() + { return f1_(), f2_(); } + + ResultType operator()(Parm1 p1) + { return f1_(p1), f2_(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f1_(p1, p2), f2_(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f1_(p1, p2, p3), f2_(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f1_(p1, p2, p3, p4), f2_(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f1_(p1, p2, p3, p4, p5), f2_(p1, p2, p3, p4, p5); } + + ResultType 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); } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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); + } + + ResultType 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) +//////////////////////////////////////////////////////////////////////////////// + +#endif // FUNCTOR_INC_ diff --git a/MSVC/1300/HierarchyGenerators.h b/MSVC/1300/HierarchyGenerators.h new file mode 100644 index 0000000..4bf690f --- /dev/null +++ b/MSVC/1300/HierarchyGenerators.h @@ -0,0 +1,423 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifdef _MSC_VER +#pragma once + +#pragma warning( push ) + + // 'class1' : base-class 'class2' is already a base-class of 'class3' +#pragma warning( disable : 4584 ) + +#endif // _MSC_VER + +#ifndef HIERARCHYGENERATORS_INC_ +#define HIERARCHYGENERATORS_INC_ + +#include "Typelist.h" +#include "TypeTraits.h" +#include "EmptyType.h" + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template GenScatterHierarchy +// Generates a scattered hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Model is a template of one arg): +// GenScatterHierarchy +// The generated class inherits all classes generated by instantiating the +// template 'Model' with the types contained in TList +//////////////////////////////////////////////////////////////////////////////// + + + template class Unit> + class GenScatterHierarchy; + + namespace Private + { + // for some reason VC7 needs the base definition altough not in use + template + struct GenScatterHierarchyHelper1 + { + template class Unit> + struct In + { + typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result; + }; + }; + + template + struct GenScatterHierarchyHelper2 + { + template class Unit> + struct In + { + typedef typename T::ERROR_THIS_INSTANCE_SELECTED Result; + }; + }; + + + template <> + struct GenScatterHierarchyHelper1 + { + template class Unit> + struct In + { + typedef GenScatterHierarchy Result; + }; + }; + + template <> + struct GenScatterHierarchyHelper2 + { + template class Unit> + struct In + { + typedef GenScatterHierarchy Result; + }; + }; + + + template <> + struct GenScatterHierarchyHelper1 + { + template class Unit> + struct In { typedef Unit Result; }; + }; + + template <> + struct GenScatterHierarchyHelper2 + { + template class Unit> + struct In { struct Result {}; }; + }; + + + template <> + struct GenScatterHierarchyHelper1 + { + template class Unit> + struct In { struct Result {}; }; + }; + + template <> + struct GenScatterHierarchyHelper2 + { + template class Unit> + struct In { struct Result {}; }; + }; + + } // namespace Private + + template class Unit> + class GenScatterHierarchy + : public Private::GenScatterHierarchyHelper1 + < + typename TL::is_Typelist::type_tag + > + ::template In::Result + + , public Private::GenScatterHierarchyHelper2 + < + typename TL::is_Typelist::type_tag + > + ::template In::Result + { + public: + + typedef typename Private::GenScatterHierarchyHelper1 + < + typename TL::is_Typelist::type_tag + > + ::template In::Result LeftBase; + + typedef typename Private::GenScatterHierarchyHelper2 + < + typename TL::is_Typelist::type_tag + > + ::template In::Result RightBase; + + + typedef typename Select + < + TL::is_Typelist::value, T, void + > + ::Result TList; + + template struct Rebind + { + typedef Unit 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 H::template Rebind::Result & + Field(H& obj) + { + return obj; + } + + template + typename H::template Rebind::Result const & + Field(H const & 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) +//////////////////////////////////////////////////////////////////////////////// + + 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 H::template Rebind::Result UnitType; + + enum { isConst = TypeTraits::isConst }; + + typedef typename Select + < + isConst, + const typename H::RightBase, + typename H::RightBase + > + ::Result RightBase; + + typedef typename Select + < + SameType >::value, + ElementType, + UnitType + > + ::Result UnqualifiedResultType; + + public: + typedef typename Select + < + isConst, + const UnqualifiedResultType, + UnqualifiedResultType + > + ::Result ResultType; + + static ResultType& Do(H& obj) + { + RightBase& rightBase = obj; + return FieldHelper::template In::Do(rightBase); + } + }; + }; + + template <> + struct FieldHelper<0> + { + template + struct In + { + private: + typedef typename H::TList::Head ElementType; + typedef typename H::template Rebind::Result UnitType; + + enum { isConst = TypeTraits::isConst }; + + typedef typename Select + < + isConst, + const typename H::LeftBase, + typename H::LeftBase + > + ::Result LeftBase; + + typedef typename Select + < + SameType >::value, + ElementType, + UnitType + > + ::Result UnqualifiedResultType; + + public: + typedef typename Select + < + isConst, + const UnqualifiedResultType, + UnqualifiedResultType + > + ::Result ResultType; + + static ResultType& Do(H& obj) + { + LeftBase& leftBase = obj; + return leftBase; + } + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Field +// Accesses a field in an object of a type generated with GenScatterHierarchy +// Invocation (obj is an object of a type H generated with GenScatterHierarchy, +// i is the index of a type in the typelist used to generate H): +// Field(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::ResultType& + Field(H& obj) + { + 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): +// GenLinearHierarchy +//////////////////////////////////////////////////////////////////////////////// + + template + < + class TList, + template class Unit, + class Root = EmptyType + > + class GenLinearHierarchy; + + namespace Private + { + + template + struct GenLinearHierarchyHelper + { + template class Unit, class Root> + struct In + { + typedef typename TList::ERROR_THIS_INSTANCE_SELECTED Result; + }; + }; + + template <> + struct GenLinearHierarchyHelper + { + template class Unit, class Root> + struct In + { + private: + typedef typename TList::Head Head; + typedef typename TList::Tail Tail; + + public: + typedef Unit< Head, GenLinearHierarchy > Result; + }; + }; + + template <> + struct GenLinearHierarchyHelper + { + template class Unit, class Root> + struct In + { + private: + typedef typename TList::Head Head; + + public: + typedef Unit Result; + }; + }; + + } // namespace Private + + template + < + class TList, + template class Unit, + class Root + > + class GenLinearHierarchy + : public Private::GenLinearHierarchyHelper + < + typename TL::is_Typelist::type_tag + > + ::template In::Result + { + ASSERT_TYPELIST(TList); // TList must not be NullType + + public: + typedef typename Private::GenLinearHierarchyHelper + < + typename TL::is_Typelist::type_tag + > + ::template In::Result LinBase; + }; + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // HIERARCHYGENERATORS_INC_ + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif // _MSC_VER + diff --git a/MSVC/1300/LokiTypeInfo.h b/MSVC/1300/LokiTypeInfo.h new file mode 100644 index 0000000..ee6701c --- /dev/null +++ b/MSVC/1300/LokiTypeInfo.h @@ -0,0 +1,107 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef TYPEINFO_INC_ +#define TYPEINFO_INC_ + +#include +#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!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPEINFO_INC_ diff --git a/MSVC/1300/MinMax.h b/MSVC/1300/MinMax.h new file mode 100644 index 0000000..bdea141 --- /dev/null +++ b/MSVC/1300/MinMax.h @@ -0,0 +1,112 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef MINMAX_INC_ +#define MINMAX_INC_ + +#include "Typelist.h" +#include "TypeTraits.h" + +namespace Private +{ + typedef TYPELIST_14( + const bool, + const char, + const signed char, + const unsigned char, + const wchar_t, + const short int, + const unsigned short int, + const int, + const unsigned int, + const long int, + const unsigned long int, + const float, + const double, + const long double) + ArithTypes; +} + +template +class MinMaxTraits +{ + typedef typename Loki::Select::exists, + L, R>::Result + T1; + + enum { pos1 = Loki::TL::IndexOf::value }; + enum { pos2 = Loki::TL::IndexOf::value }; + typedef Loki::Select::Result T2; + + enum { rConst = Loki::TypeTraits::isConst >= + Loki::TypeTraits::isConst }; + enum { l2r = rConst && Loki::Conversion< + typename Loki::TypeTraits::NonConstType&, + typename Loki::TypeTraits::NonConstType&>::exists }; + typedef typename Loki::Select::Result T3; + + enum { lConst = Loki::TypeTraits::isConst >= + Loki::TypeTraits::isConst }; + enum { r2l = lConst && Loki::Conversion< + typename Loki::TypeTraits::NonConstType&, + typename Loki::TypeTraits::NonConstType&>::exists }; +public: + typedef typename Loki::Select::Result Result; +}; + +template +typename MinMaxTraits::Result +Min(L& lhs, R& rhs) +{ if (lhs < rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Min(const L& lhs, R& rhs) +{ if (lhs < rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Min(L& lhs, const R& rhs) +{ if (lhs < rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Min(const L& lhs, const R& rhs) +{ if (lhs < rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Max(L& lhs, R& rhs) +{ if (lhs > rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Max(const L& lhs, R& rhs) +{ if (lhs > rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Max(L& lhs, const R& rhs) +{ if (lhs > rhs) return lhs; return rhs; } + +template +typename MinMaxTraits::Result +Max(const L& lhs, const R& rhs) +{ if (lhs > rhs) return lhs; return rhs; } + + +#endif // MINMAX_INC_ diff --git a/MSVC/1300/MultiMethods.h b/MSVC/1300/MultiMethods.h new file mode 100644 index 0000000..21c6bd8 --- /dev/null +++ b/MSVC/1300/MultiMethods.h @@ -0,0 +1,418 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef MULTIMETHODS_INC_ +#define MULTIMETHODS_INC_ + +#include "Typelist.h" +#include "LokiTypeInfo.h" +#include "Functor.h" +#include "AssocVector.h" + +//////////////////////////////////////////////////////////////////////////////// +// IMPORTANT NOTE: +// The double dispatchers implemented below differ from the excerpts shown in +// the book - they are simpler while respecting the same interface. +//////////////////////////////////////////////////////////////////////////////// + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template InvocationTraits (helper) +// Helps implementing optional symmetry +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + 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 = 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 = 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) + { + DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun); + } + + template + bool Remove() + { + 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); + } + +//////////////////////////////////////////////////////////////////////////////// +// class template StaticCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template + struct StaticCaster + { + static To& Cast(From& obj) + { + return static_cast(obj); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DynamicCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template + struct DynamicCaster + { + static To& Cast(From& obj) + { + return dynamic_cast(obj); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Private::FnDispatcherHelper +// Implements trampolines and argument swapping used by FnDispatcher +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + 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 CastingPolicy = DynamicCaster, + template + class DispatcherBackend = BasicDispatcher> + class FnDispatcher + { + DispatcherBackend backEnd_; + + public: + template + void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&)) + { + return backEnd_.Add(pFun); + } + + template + void Add() + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy, + CastingPolicy, + callback> Local; + + Add(&Local::Trampoline); + } + + template + void Add() + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy, + CastingPolicy, + callback> Local; + + Add(&Local::Trampoline); + if (symmetric) + { + Add(&Local::TrampolineR); + } + } + + template + void Remove() + { + backEnd_.Remove(); + } + + 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 CastingPolicy = DynamicCaster, + template + class DispatcherBackend = BasicDispatcher> + class FunctorDispatcher + { + typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; + typedef Functor FunctorType; + + DispatcherBackend backEnd_; + + public: + template + void Add(const Fun& fun) + { + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy, + CastingPolicy, + Fun, false> Adapter; + + backEnd_.Add(FunctorType(Adapter(fun))); + } + template + void Add(const Fun& fun) + { + Add(fun); + + if (symmetric) + { + // Note: symmetry only makes sense where BaseLhs==BaseRhs + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseLhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy, + CastingPolicy, + Fun, true> AdapterR; + + backEnd_.Add(FunctorType(AdapterR(fun))); + } + } + + template + void Remove() + { + backEnd_.Remove(); + } + + ResultType Go(BaseLhs& lhs, BaseRhs& rhs) + { + return backEnd_.Go(lhs, rhs); + } + }; +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/MSVC/1300/NullType.h b/MSVC/1300/NullType.h index c599315..e42a01d 100644 --- a/MSVC/1300/NullType.h +++ b/MSVC/1300/NullType.h @@ -13,7 +13,7 @@ // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// -// Last update: June 20, 2001 +// Last update: May 19, 2002 #ifndef NULLTYPE_INC_ #define NULLTYPE_INC_ @@ -26,12 +26,19 @@ namespace Loki // Useful as an end marker in typelists //////////////////////////////////////////////////////////////////////////////// - class NullType {}; + class NullType + { + public: + struct Head { private: Head(); }; + struct Tail { private: Tail(); }; + }; } -//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// // Change log: // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) //////////////////////////////////////////////////////////////////////////////// #endif // NULLTYPE_INC_ + diff --git a/MSVC/1300/Singleton.cpp b/MSVC/1300/Singleton.cpp new file mode 100644 index 0000000..57899d2 --- /dev/null +++ b/MSVC/1300/Singleton.cpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: June 20, 2001 + +#include "Singleton.h" + +using namespace Loki::Private; + +Loki::Private::TrackerArray Loki::Private::pTrackerArray = 0; +unsigned int Loki::Private::elements = 0; + +//////////////////////////////////////////////////////////////////////////////// +// function AtExitFn +// Ensures proper destruction of objects with longevity +//////////////////////////////////////////////////////////////////////////////// + +void Loki::Private::AtExitFn() +{ + assert(elements > 0 && pTrackerArray != 0); + // Pick the element at the top of the stack + LifetimeTracker* pTop = pTrackerArray[elements - 1]; + // Remove that object off the stack + // Don't check errors - realloc with less memory + // can't fail + pTrackerArray = static_cast(std::realloc( + pTrackerArray, sizeof(*pTrackerArray) * --elements)); + // Destroy the element + delete pTop; +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// diff --git a/MSVC/1300/Singleton.h b/MSVC/1300/Singleton.h new file mode 100644 index 0000000..1a232ed --- /dev/null +++ b/MSVC/1300/Singleton.h @@ -0,0 +1,440 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef SINGLETON_INC_ +#define SINGLETON_INC_ + +#include "Threads.h" +#include +#include +#include +#include +#include + +namespace Loki +{ + namespace Private + { +//////////////////////////////////////////////////////////////////////////////// +// class LifetimeTracker +// Helper class for SetLongevity +//////////////////////////////////////////////////////////////////////////////// + + class LifetimeTracker + { + public: + LifetimeTracker(unsigned int x) : longevity_(x) + {} + + virtual ~LifetimeTracker() = 0; + + static bool Compare(const LifetimeTracker* lhs, + const LifetimeTracker* rhs) + { + return lhs->longevity_ > rhs->longevity_; + } + + private: + unsigned int longevity_; + }; + + // Definition required + inline LifetimeTracker::~LifetimeTracker() {} + + // Helper data + typedef LifetimeTracker** TrackerArray; + extern TrackerArray pTrackerArray; + extern unsigned int elements; + + // Helper destroyer function + template + 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( + 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 + std::atexit(Private::AtExitFn); + } + +//////////////////////////////////////////////////////////////////////////////// +// class template CreateUsingNew +// Implementation of the CreationPolicy used by SingletonHolder +// Creates objects using a straight call to the new operator +//////////////////////////////////////////////////////////////////////////////// + + template struct CreateUsingNew + { + static T* Create() + { return new T; } + + static void Destroy(T* p) + { delete p; } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template CreateUsingNew +// Implementation of the CreationPolicy used by SingletonHolder +// Creates objects using a call to std::malloc, followed by a call to the +// placement new operator +//////////////////////////////////////////////////////////////////////////////// + + template struct CreateUsingMalloc + { + static T* Create() + { + void* p = std::malloc(sizeof(T)); + if (!p) return 0; + return new(p) T; + } + + static void Destroy(T* p) + { + p->~T(); + std::free(p); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template CreateStatic +// Implementation of the CreationPolicy used by SingletonHolder +// Creates an object in static memory +// Implementation is slightly nonportable because it uses the MaxAlign trick +// (an union of all types to ensure proper memory alignment). This trick is +// nonportable in theory but highly portable in practice. +//////////////////////////////////////////////////////////////////////////////// + + template struct CreateStatic + { +#ifdef _MSC_VER +#pragma warning( push ) + // alignment of a member was sensitive to packing +#pragma warning( disable : 4121 ) +#endif // _MSC_VER + union MaxAlign + { + char t_[sizeof(T)]; + short int shortInt_; + int int_; + long int longInt_; + float float_; + double double_; + long double longDouble_; + struct Test; + int Test::* pMember_; + int (Test::*pMemberFn_)(int); + }; +#ifdef _MSC_VER +#pragma warning( pop ) +#endif // _MSC_VER + + static T* Create() + { + static MaxAlign staticMemory_; + return new(&staticMemory_) T; + } + + static void Destroy(T* p) + { + p->~T(); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultLifetime +// Implementation of the LifetimePolicy used by SingletonHolder +// Schedules an object's destruction as per C++ rules +// Forwards to std::atexit +//////////////////////////////////////////////////////////////////////////////// + + template + struct DefaultLifetime + { + static void ScheduleDestruction(T*, void (*pFun)()) + { std::atexit(pFun); } + + static void OnDeadReference() + { throw std::logic_error("Dead Reference Detected"); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template PhoenixSingleton +// Implementation of the LifetimePolicy used by SingletonHolder +// Schedules an object's destruction as per C++ rules, and it allows object +// recreation by not throwing an exception from OnDeadReference +//////////////////////////////////////////////////////////////////////////////// + + template + class PhoenixSingleton + { + public: + static void ScheduleDestruction(T*, void (*pFun)()) + { +#ifndef ATEXIT_FIXED + if (!destroyedOnce_) +#endif + std::atexit(pFun); + } + + static void OnDeadReference() + { +#ifndef ATEXIT_FIXED + destroyedOnce_ = true; +#endif + } + + private: +#ifndef ATEXIT_FIXED + static bool destroyedOnce_; +#endif + }; + +#ifndef ATEXIT_FIXED + template bool PhoenixSingleton::destroyedOnce_ = false; +#endif + +//////////////////////////////////////////////////////////////////////////////// +// class template Adapter +// Helper for SingletonWithLongevity below +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template + struct Adapter + { + void operator()(T*) { return pFun_(); } + void (*pFun_)(); + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template SingletonWithLongevity +// Implementation of the LifetimePolicy used by SingletonHolder +// Schedules an object's destruction in order of their longevities +// Assumes a visible function GetLongevity(T*) that returns the longevity of the +// object +//////////////////////////////////////////////////////////////////////////////// + + template + class SingletonWithLongevity + { + public: + static void ScheduleDestruction(T* pObj, void (*pFun)()) + { + Private::Adapter adapter = { pFun }; + SetLongevity(pObj, GetLongevity(pObj), adapter); + } + + static void OnDeadReference() + { throw std::logic_error("Dead Reference Detected"); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDestroy +// Implementation of the LifetimePolicy used by SingletonHolder +// Never destroys the object +//////////////////////////////////////////////////////////////////////////////// + + template + struct NoDestroy + { + static void ScheduleDestruction(T*, void (*)()) + {} + + static void OnDeadReference() + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template SingletonHolder +// Provides Singleton amenities for a type T +// To protect that type from spurious instantiations, you have to protect it +// yourself. +//////////////////////////////////////////////////////////////////////////////// + + template + < + class ClientType, + class ThreadingModelType, + class PtrInstanceType + > + class SingletonHolderStaticData + { + friend ClientType; // illegal (11.4/2) but works with VC + static ThreadingModelType s_ThreadingModelData; + static PtrInstanceType s_pInstance; + static bool s_destroyed; + }; + + template + M SingletonHolderStaticData::s_ThreadingModelData; + + template + P SingletonHolderStaticData::s_pInstance; + + template + bool SingletonHolderStaticData::s_destroyed; + + template + < + typename T, + template class CreationPolicy = CreateUsingNew, + template class LifetimePolicy = DefaultLifetime, + template class ThreadingModel = SingleThreaded + > + class SingletonHolder + { + typedef typename ThreadingModel::VolatileType PtrInstanceType; + + typedef SingletonHolderStaticData + < + SingletonHolder, + ThreadingModel, + PtrInstanceType + > + MySingletonHolderStaticData; + + public: + static T& Instance() + { + if (!pInstance_()) + { + MakeInstance(); + } + return *pInstance_(); + } + + private: + // Helpers + static void MakeInstance() + { + typename ThreadingModel::Lock guard( + MySingletonHolderStaticData::s_ThreadingModelData); + + (void)guard; + + if (!pInstance_()) + { + if (destroyed_()) + { + LifetimePolicy::OnDeadReference(); + destroyed_() = false; + } + + pInstance_() = CreationPolicy::Create(); + + LifetimePolicy::ScheduleDestruction + ( + pInstance_(), + &DestroySingleton + ); + } + } + + static void DestroySingleton() + { + assert(!destroyed_()); + CreationPolicy::Destroy(pInstance_()); + pInstance_() = 0; + destroyed_() = true; + } + + // Protection + SingletonHolder(); + + // Data + static PtrInstanceType &pInstance_() + { + return MySingletonHolderStaticData::s_pInstance; + } + + static bool &destroyed_() + { + return MySingletonHolderStaticData::s_destroyed; + } + }; + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // SINGLETON_INC_ diff --git a/MSVC/1300/SmallObj.cpp b/MSVC/1300/SmallObj.cpp new file mode 100644 index 0000000..e7a8585 --- /dev/null +++ b/MSVC/1300/SmallObj.cpp @@ -0,0 +1,418 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: March 20, 2001 + +#include "SmallObj.h" +#include +#include + +using namespace Loki; + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Chunk::Init +// Initializes a chunk object +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Chunk::Init(std::size_t blockSize, unsigned char blocks) +{ + assert(blockSize > 0); + assert(blocks > 0); + // Overflow check + assert((blockSize * blocks) / blockSize == blocks); + + pData_ = new unsigned char[blockSize * blocks]; + Reset(blockSize, blocks); +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Chunk::Reset +// Clears an already allocated chunk +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Chunk::Reset(std::size_t blockSize, unsigned char blocks) +{ + assert(blockSize > 0); + assert(blocks > 0); + // Overflow check + assert((blockSize * blocks) / blockSize == blocks); + + firstAvailableBlock_ = 0; + blocksAvailable_ = blocks; + + unsigned char i = 0; + unsigned char* p = pData_; + for (; i != blocks; p += blockSize) + { + *p = ++i; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Chunk::Release +// Releases the data managed by a chunk +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Chunk::Release() +{ + delete[] pData_; +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Chunk::Allocate +// Allocates a block from a chunk +//////////////////////////////////////////////////////////////////////////////// + +void* FixedAllocator::Chunk::Allocate(std::size_t blockSize) +{ + if (!blocksAvailable_) return 0; + + assert((firstAvailableBlock_ * blockSize) / blockSize == + firstAvailableBlock_); + + unsigned char* pResult = + pData_ + (firstAvailableBlock_ * blockSize); + firstAvailableBlock_ = *pResult; + --blocksAvailable_; + + return pResult; +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Chunk::Deallocate +// Dellocates a block from a chunk +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Chunk::Deallocate(void* p, std::size_t blockSize) +{ + assert(p >= pData_); + + unsigned char* toRelease = static_cast(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(std::size_t blockSize) + : blockSize_(blockSize) + , allocChunk_(0) + , deallocChunk_(0) +{ + assert(blockSize_ > 0); + + prev_ = next_ = this; + + std::size_t numBlocks = DEFAULT_CHUNK_SIZE / blockSize; + if (numBlocks > UCHAR_MAX) numBlocks = UCHAR_MAX; + else if (numBlocks == 0) numBlocks = 8 * blockSize; + + numBlocks_ = static_cast(numBlocks); + assert(numBlocks_ == numBlocks); +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::FixedAllocator(const FixedAllocator&) +// Creates a FixedAllocator object of a fixed block size +//////////////////////////////////////////////////////////////////////////////// + +FixedAllocator::FixedAllocator(const FixedAllocator& rhs) + : blockSize_(rhs.blockSize_) + , numBlocks_(rhs.numBlocks_) + , chunks_(rhs.chunks_) +{ + prev_ = &rhs; + next_ = rhs.next_; + rhs.next_->prev_ = this; + rhs.next_ = this; + + allocChunk_ = rhs.allocChunk_ + ? &chunks_.front() + (rhs.allocChunk_ - &rhs.chunks_.front()) + : 0; + + deallocChunk_ = rhs.deallocChunk_ + ? &chunks_.front() + (rhs.deallocChunk_ - &rhs.chunks_.front()) + : 0; +} + +FixedAllocator& FixedAllocator::operator=(const FixedAllocator& rhs) +{ + FixedAllocator copy(rhs); + copy.Swap(*this); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::~FixedAllocator +//////////////////////////////////////////////////////////////////////////////// + +FixedAllocator::~FixedAllocator() +{ + if (prev_ != this) + { + prev_->next_ = next_; + next_->prev_ = prev_; + return; + } + + assert(prev_ == next_); + Chunks::iterator i = chunks_.begin(); + for (; i != chunks_.end(); ++i) + { + assert(i->blocksAvailable_ == numBlocks_); + i->Release(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Swap +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Swap(FixedAllocator& rhs) +{ + using namespace std; + + swap(blockSize_, rhs.blockSize_); + swap(numBlocks_, rhs.numBlocks_); + chunks_.swap(rhs.chunks_); + swap(allocChunk_, rhs.allocChunk_); + swap(deallocChunk_, rhs.deallocChunk_); +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Allocate +// Allocates a block of fixed size +//////////////////////////////////////////////////////////////////////////////// + +void* FixedAllocator::Allocate() +{ + if (allocChunk_ == 0 || allocChunk_->blocksAvailable_ == 0) + { + Chunks::iterator i = chunks_.begin(); + for (;; ++i) + { + if (i == chunks_.end()) + { + // Initialize + chunks_.reserve(chunks_.size() + 1); + Chunk newChunk; + newChunk.Init(blockSize_, numBlocks_); + chunks_.push_back(newChunk); + allocChunk_ = &chunks_.back(); + deallocChunk_ = &chunks_.front(); + break; + } + if (i->blocksAvailable_ > 0) + { + allocChunk_ = &*i; + break; + } + } + } + assert(allocChunk_ != 0); + assert(allocChunk_->blocksAvailable_ > 0); + + return allocChunk_->Allocate(blockSize_); +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::Deallocate +// Deallocates a block previously allocated with Allocate +// (undefined behavior if called with the wrong pointer) +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::Deallocate(void* p) +{ + assert(!chunks_.empty()); + assert(&chunks_.front() <= deallocChunk_); + assert(&chunks_.back() >= deallocChunk_); + + deallocChunk_ = VicinityFind(p); + assert(deallocChunk_); + + DoDeallocate(p); +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::VicinityFind (internal) +// Finds the chunk corresponding to a pointer, using an efficient search +//////////////////////////////////////////////////////////////////////////////// + +FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p) +{ + assert(!chunks_.empty()); + assert(deallocChunk_); + + const std::size_t chunkLength = numBlocks_ * blockSize_; + + Chunk* lo = deallocChunk_; + Chunk* hi = deallocChunk_ + 1; + Chunk* loBound = &chunks_.front(); + Chunk* hiBound = &chunks_.back() + 1; + + for (;;) + { + if (lo) + { + if (p >= lo->pData_ && p < lo->pData_ + chunkLength) + { + return lo; + } + if (lo == loBound) lo = 0; + else --lo; + } + + if (hi) + { + if (p >= hi->pData_ && p < hi->pData_ + chunkLength) + { + return hi; + } + if (++hi == hiBound) hi = 0; + } + } + + // assert(false); + // return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// FixedAllocator::DoDeallocate (internal) +// Performs deallocation. Assumes deallocChunk_ points to the correct chunk +//////////////////////////////////////////////////////////////////////////////// + +void FixedAllocator::DoDeallocate(void* p) +{ + assert(deallocChunk_->pData_ <= p); + assert(deallocChunk_->pData_ + numBlocks_ * blockSize_ > p); + + // call into the chunk, will adjust the inner list but won't release memory + deallocChunk_->Deallocate(p, blockSize_); + + if (deallocChunk_->blocksAvailable_ == numBlocks_) + { + // deallocChunk_ is completely free, should we release it? + + Chunk& lastChunk = chunks_.back(); + + if (&lastChunk == deallocChunk_) + { + // check if we have two last chunks empty + + if (chunks_.size() > 1 && + deallocChunk_[-1].blocksAvailable_ == numBlocks_) + { + // Two free chunks, discard the last one + lastChunk.Release(); + chunks_.pop_back(); + allocChunk_ = deallocChunk_ = &chunks_.front(); + } + return; + } + + if (lastChunk.blocksAvailable_ == numBlocks_) + { + // Two free blocks, discard one + lastChunk.Release(); + chunks_.pop_back(); + allocChunk_ = deallocChunk_; + } + else + { + // move the empty chunk to the end + std::swap(*deallocChunk_, lastChunk); + allocChunk_ = &chunks_.back(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// SmallObjAllocator::SmallObjAllocator +// Creates an allocator for small objects given chunk size and maximum 'small' +// object size +//////////////////////////////////////////////////////////////////////////////// + +SmallObjAllocator::SmallObjAllocator( + std::size_t chunkSize, + std::size_t maxObjectSize) + : pLastAlloc_(0), pLastDealloc_(0) + , chunkSize_(chunkSize), maxObjectSize_(maxObjectSize) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// SmallObjAllocator::Allocate +// Allocates 'numBytes' memory +// Uses an internal pool of FixedAllocator objects for small objects +//////////////////////////////////////////////////////////////////////////////// + +void* SmallObjAllocator::Allocate(std::size_t numBytes) +{ + if (numBytes > maxObjectSize_) return operator new(numBytes); + + if (pLastAlloc_ && pLastAlloc_->BlockSize() == numBytes) + { + return pLastAlloc_->Allocate(); + } + Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes); + if (i == pool_.end() || i->BlockSize() != numBytes) + { + i = pool_.insert(i, FixedAllocator(numBytes)); + pLastDealloc_ = &*pool_.begin(); + } + pLastAlloc_ = &*i; + return pLastAlloc_->Allocate(); +} + +//////////////////////////////////////////////////////////////////////////////// +// SmallObjAllocator::Deallocate +// Deallocates memory previously allocated with Allocate +// (undefined behavior if you pass any other pointer) +//////////////////////////////////////////////////////////////////////////////// + +void SmallObjAllocator::Deallocate(void* p, std::size_t numBytes) +{ + if (numBytes > maxObjectSize_) return operator delete(p); + + if (pLastDealloc_ && pLastDealloc_->BlockSize() == numBytes) + { + pLastDealloc_->Deallocate(p); + return; + } + Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes); + assert(i != pool_.end()); + assert(i->BlockSize() == numBytes); + pLastDealloc_ = &*i; + pLastDealloc_->Deallocate(p); +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// March 20: fix exception safety issue in FixedAllocator::Allocate +// (thanks to Chris Udazvinis for pointing that out) +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// diff --git a/MSVC/1300/SmallObj.h b/MSVC/1300/SmallObj.h new file mode 100644 index 0000000..4c5a2f0 --- /dev/null +++ b/MSVC/1300/SmallObj.h @@ -0,0 +1,211 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef SMALLOBJ_INC_ +#define SMALLOBJ_INC_ + +#include "Threads.h" +#include "Singleton.h" +#include +#include + +#ifndef DEFAULT_CHUNK_SIZE +#define DEFAULT_CHUNK_SIZE 4096 +#endif + +#ifndef MAX_SMALL_OBJECT_SIZE +#define MAX_SMALL_OBJECT_SIZE 64 +#endif + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class FixedAllocator +// Offers services for allocating fixed-sized objects +//////////////////////////////////////////////////////////////////////////////// + + class FixedAllocator + { + public: // VC7 access control BUG + class Chunk + { + friend FixedAllocator; + + void Init(std::size_t blockSize, unsigned char blocks); + void* Allocate(std::size_t blockSize); + void Deallocate(void* p, std::size_t blockSize); + void Reset(std::size_t blockSize, unsigned char blocks); + void Release(); + unsigned char* pData_; + unsigned char + firstAvailableBlock_, + blocksAvailable_; + }; + + private: + // Internal functions + void DoDeallocate(void* p); + Chunk* VicinityFind(void* p); + + // Data + std::size_t blockSize_; + unsigned char numBlocks_; + typedef std::vector Chunks; + Chunks chunks_; + Chunk* allocChunk_; + Chunk* deallocChunk_; + // For ensuring proper copy semantics + mutable const FixedAllocator* prev_; + mutable const FixedAllocator* next_; + + public: + // Create a FixedAllocator able to manage blocks of 'blockSize' size + explicit FixedAllocator(std::size_t blockSize = 0); + FixedAllocator(const FixedAllocator&); + FixedAllocator& operator=(const FixedAllocator&); + ~FixedAllocator(); + + void Swap(FixedAllocator& rhs); + + // Allocate a memory block + void* Allocate(); + // Deallocate a memory block previously allocated with Allocate() + // (if that's not the case, the behavior is undefined) + void Deallocate(void* p); + // Returns the block size with which the FixedAllocator was initialized + std::size_t BlockSize() const + { return blockSize_; } + // Comparison operator for sorting + bool operator<(std::size_t rhs) const + { return BlockSize() < rhs; } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class SmallObjAllocator +// Offers services for allocating small-sized objects +//////////////////////////////////////////////////////////////////////////////// + + class SmallObjAllocator + { + public: + SmallObjAllocator( + std::size_t chunkSize, + std::size_t maxObjectSize); + + void* Allocate(std::size_t numBytes); + void Deallocate(void* p, std::size_t size); + + private: + SmallObjAllocator(const SmallObjAllocator&); + SmallObjAllocator& operator=(const SmallObjAllocator&); + + typedef std::vector Pool; + Pool pool_; + FixedAllocator* pLastAlloc_; + FixedAllocator* pLastDealloc_; + std::size_t chunkSize_; + std::size_t maxObjectSize_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class SmallObject +// Base class for polymorphic small objects, offers fast +// allocations/deallocations +//////////////////////////////////////////////////////////////////////////////// + + template + < + class ClientType, + class ThreadingModelType + > + class SmallObjectStaticData + { + friend ClientType; // illegal (11.4/2) but works with VC + static ThreadingModelType s_ThreadingModelData; + }; + + template + M SmallObjectStaticData::s_ThreadingModelData; + + template + < + template class ThreadingModel = DEFAULT_THREADING, + std::size_t chunkSize = DEFAULT_CHUNK_SIZE, + std::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE + > + class SmallObject : public ThreadingModel< + SmallObject > + { + typedef ThreadingModel< SmallObject > MyThreadingModel; + + typedef SmallObjectStaticData + < + SmallObject, + MyThreadingModel + > + MySmallObjectStaticData; + + struct MySmallObjAllocator : public SmallObjAllocator + { + MySmallObjAllocator() + : SmallObjAllocator(chunkSize, maxSmallObjectSize) + {} + }; + // The typedef below would make things much simpler, + // but MWCW won't like it + // typedef SingletonHolder MyAllocator; + + public: + static void* operator new(std::size_t size) + { +#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0) + typename MyThreadingModel::Lock lock( + MySmallObjectStaticData::s_ThreadingModelData); + (void)lock; // get rid of warning + + return SingletonHolder::Instance().Allocate(size); +#else + return ::operator new(size); +#endif + } + static void operator delete(void* p, std::size_t size) + { +#if (MAX_SMALL_OBJECT_SIZE != 0) && (DEFAULT_CHUNK_SIZE != 0) + typename MyThreadingModel::Lock lock( + MySmallObjectStaticData::s_ThreadingModelData); + (void)lock; // get rid of warning + + SingletonHolder::Instance().Deallocate(p, size); +#else + ::operator delete(p, size); +#endif + } + virtual ~SmallObject() {} + }; +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) +//////////////////////////////////////////////////////////////////////////////// + +#endif // SMALLOBJ_INC_ diff --git a/MSVC/1300/SmartPtr.h b/MSVC/1300/SmartPtr.h new file mode 100644 index 0000000..667b7bb --- /dev/null +++ b/MSVC/1300/SmartPtr.h @@ -0,0 +1,1329 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: May 19, 2002 + +#ifndef 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 "static_check.h" +#include +#include +#include + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultSPStorage +// Implementation of the StoragePolicy used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + template + class DefaultSPStorage + { + protected: + 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 + DefaultSPStorage(const DefaultSPStorage&) + {} + + template + DefaultSPStorage(const DefaultSPStorage&) + {} + + 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_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// 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; + } + + RefCounted(const RefCounted& rhs) + : pCount_(rhs.pCount_) + {} + + // MWCW lacks template friends, hence the following kludge + template + RefCounted(const RefCounted& rhs) + : pCount_(reinterpret_cast(rhs).pCount_) + {} + + P Clone(const P& val) + { + ++*pCount_; + return val; + } + + bool Release(const P&, bool = false) + { + 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_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template RefCountedMT +// Implementation of the OwnershipPolicy used by SmartPtr +// Implements external reference counting for multithreaded programs +//////////////////////////////////////////////////////////////////////////////// + template