From 4bfc42e511576637314030e9b0195492f2138be7 Mon Sep 17 00:00:00 2001 From: humesikkins Date: Thu, 27 Feb 2003 15:55:48 +0000 Subject: [PATCH] different workaround for void returns than visitor.h git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@106 7ec92016-0320-0410-acc4-a06ded1c099a --- MSVC/1200/VisitorOld.h | 521 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 521 insertions(+) create mode 100644 MSVC/1200/VisitorOld.h diff --git a/MSVC/1200/VisitorOld.h b/MSVC/1200/VisitorOld.h new file mode 100644 index 0000000..c1e9078 --- /dev/null +++ b/MSVC/1200/VisitorOld.h @@ -0,0 +1,521 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: Feb 23, 2003 +// +// +// The original visitor implementation depends heavily on the possibility +// to return an expression of type "cv void" from a functions with a return +// type of cv void (6.6.3). +// Unfortunately the MSVC 6.0 does not allow that. Because I could not think +// of any transparent workaround I decided to create a set of complete new +// classes for the void-case. +// Of course this is a very unattractive solution :-( +// If you know of a better solution, please let me know. +// +// The MSVC 6.0 does not allow void to be a default value for a template parameter. +// I therefore changed all defaults to int. + +#ifndef VISITOR_INC_ +#define VISITOR_INC_ + +#include "Typelist.h" +#include "HierarchyGenerators.h" +#include "MSVC6Helpers.h" + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitor +// The base class of any Acyclic Visitor +//////////////////////////////////////////////////////////////////////////////// + + class BaseVisitor + { + public: + virtual ~BaseVisitor() {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Visitor +// The building block of Acyclic Visitor +//////////////////////////////////////////////////////////////////////////////// + template + class Visitor; +//////////////////////////////////////////////////////////////////////////////// +// class template Visitor (specialization) +// This specialization is not present in the book. It makes it easier to define +// Visitors for multiple types in a shot by using a typelist. Example: +// +// class SomeVisitor : +// public BaseVisitor // required +// public Visitor, +// public Visitor +// { +// public: +// void Visit(RasterBitmap&); // visit a RasterBitmap +// void Visit(Paragraph &); // visit a Paragraph +// }; +//////////////////////////////////////////////////////////////////////////////// +namespace Private +{ + // helper for Visitor's the left base class + template + struct VisitorImplLeft + { + template + struct In + { + typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + // helper for Visitor's the right base class + template + struct VisitorImplRight + { + template + struct In + { + typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + // simulates specialization + // class Visitor + template <> + struct VisitorImplLeft + { + template + struct In + { + struct Result + { + typedef R ReturnType; + virtual ReturnType Visit(T&) = 0; + }; + }; + }; + + // simulates the left base class for the specialization + // class Visitor, R> + template <> + struct VisitorImplLeft + { + template + struct In + { + typedef Visitor Result; + }; + }; + + template <> + struct VisitorImplRight + { + template + struct In + { + struct Result {}; + }; + }; + + // simulates the right base class for the specialization + // class Visitor, R> + template <> + struct VisitorImplRight + { + template + struct In + { + typedef Visitor Result; + }; + }; + + template <> + struct VisitorImplRight + { + template + struct In + { + struct Result {}; + }; + }; + + // MSVC 6.0 will complain if we try to let Visitor inherit + // directly from VisitorImplLeft/VisitorImplRight + template + struct VisitorImplLeftWrap + { + struct Dummy{}; + typedef typename VisitorImplLeft + < + TL::Private::IsTypelist::type_id == TL::Private::AtomList_ID ? + TL::Private::Typelist_ID : + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + template + struct VisitorImplRightWrap + { + struct Dummy{}; + typedef typename VisitorImplRight + < + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + +} + template + class Visitor : public Private::VisitorImplLeftWrap::Result, + public Private::VisitorImplRightWrap::Result + + { + public: + typedef R ReturnType; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitorImpl +// Implements non-strict visitation (you can implement only part of the Visit +// functions) +//////////////////////////////////////////////////////////////////////////////// + + template class BaseVisitorImpl; + + // class for the void-case + template class BaseVisitorImplVoid; + +namespace Private +{ + template + struct BaseVisitorImplHelper + { + template + struct In + { + typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result; + }; + }; + + template<> + struct BaseVisitorImplHelper + { + template + struct In + { + typedef typename Loki::Select< + IsVoid::value, + BaseVisitorImplVoid, + BaseVisitorImpl + >::Result Result; + //typedef BaseVisitorImpl Result; + }; + }; + + template<> + struct BaseVisitorImplHelper + { + template + struct In + { + struct Result {}; + }; + }; + + template + struct BaseVisitorImplWrap + { + struct Dummy {}; + typedef typename BaseVisitorImplHelper + < + TL::Private::IsTypelist:: + type_id == TL::Private::AtomList_ID ? + TL::Private::Typelist_ID : + TL::Private::IsTypelist::type_id + >::template In::Result TempType; + typedef VC_Base_Workaround Workaround; + typedef Workaround::LeftBase Result; + }; + + +} + + template + class BaseVisitorImpl : public Visitor, + public Private::BaseVisitorImplWrap::Result + { + ASSERT_TYPELIST(TList); + + public: + // using BaseVisitorImpl::Visit; + + virtual R Visit(typename TList::Head&) + { return R(); } + }; + + // class for the void-case + template + class BaseVisitorImplVoid : public Visitor, + public Private::BaseVisitorImplWrap::Result + { + ASSERT_TYPELIST(TList); + + public: + // using BaseVisitorImpl::Visit; + + virtual void Visit(typename TList::Head&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DefaultCatchAll +//////////////////////////////////////////////////////////////////////////////// + +template +struct DefaultCatchAll +{ + static R OnUnknownVisitor(Visited&, BaseVisitor&) + { return R(); } +}; + +// template template parameter workaround. +// use Wrapper-Classes like this to instantiate BaseVisitable +struct DefaultCatchAllWrapper +{ + template + struct In + { + typedef DefaultCatchAll type; + }; +}; + +template +struct DefaultCatchAllVoid +{ + static R OnUnknownVisitor(Visited&, BaseVisitor&) + {} +}; + +struct DefaultCatchAllVoidWrapper +{ + template + struct In + { + typedef DefaultCatchAllVoid type; + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template NonStrictVisitor +// Implements non-strict visitation (you can implement only part of the Visit +// functions) +//////////////////////////////////////////////////////////////////////////////// + + template + struct NonStrictVisitorUnit : public Base + { + typedef typename Base::ReturnType ReturnType; + ReturnType Visit(T&) + { + return ReturnType(); + } + }; + + struct NonStrictVisitorUnitWrapper + { + template + struct In + { + typedef NonStrictVisitorUnit type; + }; + }; + + + template + class NonStrictVisitor + : public GenLinearHierarchy< + TList, + NonStrictVisitorUnitWrapper, + Visitor > + { + }; + + template + struct NonStrictVisitorUnitVoid : public Base + { + typedef void ReturnType; + ReturnType Visit(T&) + { + } + }; + + struct NonStrictVisitorUnitVoidWrapper + { + template + struct In + { + typedef NonStrictVisitorUnitVoid type; + }; + }; + + + template + class NonStrictVisitorVoid + : public GenLinearHierarchy< + TList, + NonStrictVisitorUnitVoidWrapper, + Visitor > + { + }; +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitable +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename R = int/* = void */, + class CatchAll = DefaultCatchAllWrapper + > + class BaseVisitable + { + public: + typedef R ReturnType; + virtual ~BaseVisitable() {} + virtual ReturnType Accept(BaseVisitor&) = 0; + + protected: // give access only to the hierarchy + template + static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) + { + typedef ApplyInnerType2::type CatchA; + // Apply the Acyclic Visitor + if (Visitor* p = dynamic_cast*>(&guest)) + { + return p->Visit(visited); + } + return CatchA::OnUnknownVisitor(visited, guest); + } + }; + + + // class for the void-case + template + < + class CatchAll = DefaultCatchAllVoidWrapper + > + class BaseVisitableVoid + { + public: + typedef void ReturnType; + virtual ~BaseVisitableVoid() {} + virtual ReturnType Accept(BaseVisitor&) = 0; + + protected: // give access only to the hierarchy + template + static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) + { + typedef ApplyInnerType2::type CatchA; + // Apply the Acyclic Visitor + if (Visitor* p = dynamic_cast*>(&guest)) + { + p->Visit(visited); + } + CatchA::OnUnknownVisitor(visited, guest); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// macro DEFINE_VISITABLE +// Put it in every class that you want to make visitable (in addition to +// deriving it from BaseVisitable +//////////////////////////////////////////////////////////////////////////////// + +#define DEFINE_VISITABLE() \ + virtual ReturnType Accept(Loki::BaseVisitor& guest) \ + { return AcceptImpl(*this, guest); } + +#define DEFINE_VISITABLE_VOID() \ + virtual void Accept(Loki::BaseVisitor& guest) \ + { AcceptImpl(*this, guest); } + +//////////////////////////////////////////////////////////////////////////////// +// class template CyclicVisitor +// Put it in every class that you want to make visitable (in addition to +// deriving it from BaseVisitable +//////////////////////////////////////////////////////////////////////////////// + template + class CyclicVisitor : public Visitor + { + public: + typedef R ReturnType; + // using Visitor::Visit; + + template + ReturnType GenericVisit(Visited& host) + { + Visitor& subObj = *this; + return subObj.Visit(host); + } + }; + + template + class CyclicVisitorVoid : public Visitor + { + public: + typedef void ReturnType; + // using Visitor::Visit; + + template + ReturnType GenericVisit(Visited& host) + { + Visitor& subObj = *this; + subObj.Visit(host); + } + }; +//////////////////////////////////////////////////////////////////////////////// +// macro DEFINE_CYCLIC_VISITABLE +// Put it in every class that you want to make visitable by a cyclic visitor +//////////////////////////////////////////////////////////////////////////////// + +#define DEFINE_CYCLIC_VISITABLE(SomeVisitor) \ + virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \ + { return guest.GenericVisit(*this); } + +#define DEFINE_CYCLIC_VISITABLE_VOID(SomeVisitor) \ + virtual void Accept(SomeVisitor& guest) \ + { guest.GenericVisit(*this); } + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// March 20: add default argument DefaultCatchAll to BaseVisitable +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// Oct 27, 2002: ported by Benjamin Kaufmann to MSVC 6.0 +// Feb 23, 2003: Removed superfluous implementation classes and added Loki:: +// qualification to Accept's Paramter (in the macro) B.K. +//////////////////////////////////////////////////////////////////////////////// + +#endif // VISITOR_INC_ +