2003-01-06 02:26:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The Loki Library
|
|
|
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
|
|
|
// This code accompanies the book:
|
2003-03-05 23:39:15 +00:00
|
|
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
2003-01-06 02:26:33 +00:00
|
|
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
2003-03-05 23:39:15 +00:00
|
|
|
// 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
|
2003-01-06 02:26:33 +00:00
|
|
|
// permission notice appear in supporting documentation.
|
2003-03-05 23:39:15 +00:00
|
|
|
// The author or Addison-Wesley Longman make no representations about the
|
|
|
|
// suitability of this software for any purpose. It is provided "as is"
|
2003-01-06 02:26:33 +00:00
|
|
|
// without express or implied warranty.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
// Last update: Mar 06, 2003
|
|
|
|
//
|
|
|
|
// Like the original library, this port now uses void as
|
|
|
|
// default value for return types.
|
2003-01-06 02:26:33 +00:00
|
|
|
//
|
2003-02-27 15:47:47 +00:00
|
|
|
// This new of visitor.h handles void returns transparently. See
|
|
|
|
// readme.txt for an explanation of the used technique.
|
|
|
|
// However there are still two sets of macros. One for return type = void
|
|
|
|
// (DEFINE_VISITABLE_VOID, DEFINE_CYCLIC_VISITABLE_VOID) and one for return
|
|
|
|
// type != void (DEFINE_VISITABLE, DEFINE_CYCLIC_VISITABLE)
|
2003-03-05 23:39:15 +00:00
|
|
|
//
|
2003-02-27 15:47:47 +00:00
|
|
|
// If you prefer the old version of visitor.h which uses a different set of
|
2003-03-05 23:39:15 +00:00
|
|
|
// visitor classes for the return type void, define the macro
|
2003-02-27 15:47:47 +00:00
|
|
|
// USE_VISITOR_OLD_VERSION.
|
2003-03-05 23:39:15 +00:00
|
|
|
//
|
2003-02-27 15:47:47 +00:00
|
|
|
#ifdef USE_VISITOR_OLD_VERSION
|
|
|
|
#include "VisitorOld.h"
|
|
|
|
#else
|
2003-01-06 02:26:33 +00:00
|
|
|
#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() {}
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template Visitor
|
|
|
|
// The building block of Acyclic Visitor
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2003-03-05 23:39:15 +00:00
|
|
|
template <class T, typename R = Loki::Private::VoidWrap::type >
|
2003-01-06 02:26:33 +00:00
|
|
|
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:
|
|
|
|
//
|
2003-03-05 23:39:15 +00:00
|
|
|
// class SomeVisitor :
|
2003-01-06 02:26:33 +00:00
|
|
|
// public BaseVisitor // required
|
2003-03-05 23:39:15 +00:00
|
|
|
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
|
2003-01-06 02:26:33 +00:00
|
|
|
// public Visitor<Paragraph>
|
|
|
|
// {
|
|
|
|
// public:
|
|
|
|
// void Visit(RasterBitmap&); // visit a RasterBitmap
|
|
|
|
// void Visit(Paragraph &); // visit a Paragraph
|
|
|
|
// };
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
// helper for Visitor's the left base class
|
|
|
|
template <unsigned int ListId>
|
2003-03-05 23:39:15 +00:00
|
|
|
struct VisitorImplLeft
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
// helper for Visitor's the right base class
|
|
|
|
template <unsigned int ListId>
|
|
|
|
struct VisitorImplRight
|
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
// simulates specialization
|
2003-01-06 02:26:33 +00:00
|
|
|
// class Visitor<Head, R>
|
|
|
|
template <>
|
|
|
|
struct VisitorImplLeft<TL::Private::NoneList_ID>
|
|
|
|
{
|
|
|
|
template <class T, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
struct Result
|
|
|
|
{
|
|
|
|
typedef R ReturnType;
|
|
|
|
virtual ReturnType Visit(T&) = 0;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
|
|
|
// simulates the left base class for the specialization
|
2003-01-06 02:26:33 +00:00
|
|
|
// class Visitor<Typelist<Head, Tail>, R>
|
|
|
|
template <>
|
|
|
|
struct VisitorImplLeft<TL::Private::Typelist_ID>
|
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef Visitor<typename TList::Head, R> Result;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct VisitorImplRight<TL::Private::NoneList_ID>
|
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
struct Result {};
|
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
|
|
|
// simulates the right base class for the specialization
|
2003-01-06 02:26:33 +00:00
|
|
|
// class Visitor<Typelist<Head, Tail>, R>
|
|
|
|
template <>
|
|
|
|
struct VisitorImplRight<TL::Private::Typelist_ID>
|
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef Visitor<typename TList::Tail, R> Result;
|
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
template <>
|
|
|
|
struct VisitorImplRight<TL::Private::AtomList_ID>
|
|
|
|
{
|
|
|
|
template <class TList, class R>
|
|
|
|
struct In
|
|
|
|
{
|
|
|
|
struct Result {};
|
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
// MSVC 6.0 will complain if we try to let Visitor inherit
|
|
|
|
// directly from VisitorImplLeft/VisitorImplRight
|
|
|
|
template <class T, class R>
|
|
|
|
struct VisitorImplLeftWrap
|
|
|
|
{
|
|
|
|
struct Dummy{};
|
|
|
|
typedef typename VisitorImplLeft
|
|
|
|
<
|
|
|
|
TL::Private::IsTypelist<T>::type_id == TL::Private::AtomList_ID ?
|
2003-03-05 23:39:15 +00:00
|
|
|
TL::Private::Typelist_ID :
|
2003-01-06 02:26:33 +00:00
|
|
|
TL::Private::IsTypelist<T>::type_id
|
|
|
|
>::template In<T, R>::Result TempType;
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
|
|
|
typedef Workaround::LeftBase Result;
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
template <class T, class R>
|
|
|
|
struct VisitorImplRightWrap
|
|
|
|
{
|
|
|
|
struct Dummy{};
|
|
|
|
typedef typename VisitorImplRight
|
|
|
|
<
|
|
|
|
TL::Private::IsTypelist<T>::type_id
|
|
|
|
>::template In<T, R>::Result TempType;
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
|
|
|
typedef Workaround::LeftBase Result;
|
|
|
|
};
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
}
|
|
|
|
template <class T, typename R>
|
2003-03-05 23:39:15 +00:00
|
|
|
class Visitor : public Private::VisitorImplLeftWrap<T, R>::Result,
|
2003-01-06 02:26:33 +00:00
|
|
|
public Private::VisitorImplRightWrap<T, R>::Result
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef R ReturnType;
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template BaseVisitorImpl
|
|
|
|
// Implements non-strict visitation (you can implement only part of the Visit
|
|
|
|
// functions)
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
template <class TList, typename R = Loki::Private::VoidWrap::type >
|
|
|
|
class BaseVisitorImpl;
|
2003-01-06 02:26:33 +00:00
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
template <unsigned int ListTag>
|
|
|
|
struct BaseVisitorImplHelper
|
|
|
|
{
|
|
|
|
template <typename T, typename R>
|
2003-03-05 23:39:15 +00:00
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
template<>
|
2003-01-06 02:26:33 +00:00
|
|
|
struct BaseVisitorImplHelper<TL::Private::Typelist_ID>
|
|
|
|
{
|
|
|
|
template <typename TList, typename R>
|
2003-03-05 23:39:15 +00:00
|
|
|
struct In
|
|
|
|
{
|
|
|
|
typedef BaseVisitorImpl<TList, R> Result;
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
template<>
|
2003-01-06 02:26:33 +00:00
|
|
|
struct BaseVisitorImplHelper<TL::Private::NullType_ID>
|
|
|
|
{
|
|
|
|
template <typename TList, typename R>
|
2003-03-05 23:39:15 +00:00
|
|
|
struct In
|
|
|
|
{
|
|
|
|
struct Result {};
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
|
|
|
template <class T, class R>
|
2003-01-06 02:26:33 +00:00
|
|
|
struct BaseVisitorImplWrap
|
2003-03-05 23:39:15 +00:00
|
|
|
{
|
2003-01-06 02:26:33 +00:00
|
|
|
struct Dummy {};
|
|
|
|
typedef typename BaseVisitorImplHelper
|
|
|
|
<
|
|
|
|
TL::Private::IsTypelist<typename T::Tail>::
|
2003-03-05 23:39:15 +00:00
|
|
|
type_id == TL::Private::AtomList_ID ?
|
|
|
|
TL::Private::Typelist_ID :
|
2003-01-06 02:26:33 +00:00
|
|
|
TL::Private::IsTypelist<typename T::Tail>::type_id
|
|
|
|
>::template In<typename T::Tail, R>::Result TempType;
|
|
|
|
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
|
|
|
|
typedef Workaround::LeftBase Result;
|
|
|
|
};
|
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
template <class TList, class R>
|
|
|
|
struct BaseVisitorImplBase : public Visitor<typename TList::Head, R>,
|
|
|
|
public Private::BaseVisitorImplWrap<TList, R>::Result
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
ASSERT_TYPELIST(TList);
|
|
|
|
virtual R Visit(typename TList::Head&)
|
|
|
|
{ return R(); }
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
~BaseVisitorImplBase() {}
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
template <class TList, class R>
|
|
|
|
struct BaseVisitorImplVoidBase : public Visitor<typename TList::Head, R>,
|
|
|
|
public Private::BaseVisitorImplWrap<TList, R>::Result
|
|
|
|
{
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
ASSERT_TYPELIST(TList);
|
|
|
|
virtual R Visit(typename TList::Head&)
|
|
|
|
{ }
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
~BaseVisitorImplVoidBase() {}
|
2003-03-05 23:39:15 +00:00
|
|
|
};
|
2003-01-06 02:26:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
template <class TList, typename R>
|
|
|
|
class BaseVisitorImpl : public Select
|
|
|
|
<
|
|
|
|
Private::IsVoid<R>::value,
|
|
|
|
Private::BaseVisitorImplVoidBase<TList,R>,
|
|
|
|
Private::BaseVisitorImplBase<TList, R>
|
|
|
|
>::Result
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
ASSERT_TYPELIST(TList);
|
|
|
|
|
|
|
|
public:
|
2003-02-27 15:47:47 +00:00
|
|
|
// using BaseVisitorImpl<Tail, R>::Visit;
|
2003-01-06 02:26:33 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template DefaultCatchAll
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename R, typename Visited>
|
|
|
|
struct DefaultCatchAll
|
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
|
|
|
{ return R(); }
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
template <typename R, typename Visited>
|
|
|
|
struct DefaultCatchAllVoid
|
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
static R OnUnknownVisitor(Visited&, BaseVisitor&)
|
|
|
|
{ }
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
// template template parameter workaround.
|
|
|
|
// use Wrapper-Classes like this to instantiate BaseVisitable
|
|
|
|
struct DefaultCatchAllWrapper
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
template <class R, class Visited>
|
|
|
|
struct In
|
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
typedef typename Select<Private::IsVoid<R>::value,
|
|
|
|
DefaultCatchAllVoid<R, Visited>,
|
|
|
|
DefaultCatchAll<R, Visited>
|
|
|
|
>::Result type;
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template NonStrictVisitor
|
|
|
|
// Implements non-strict visitation (you can implement only part of the Visit
|
|
|
|
// functions)
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T, class Base>
|
2003-02-27 15:47:47 +00:00
|
|
|
struct NonStrictVisitorUnit : public Base
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
typedef typename Base::ReturnType ReturnType;
|
2003-01-06 02:26:33 +00:00
|
|
|
ReturnType Visit(T&)
|
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
return ReturnType();
|
|
|
|
}
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
template <class T, class Base>
|
2003-02-27 15:47:47 +00:00
|
|
|
struct NonStrictVisitorUnitVoid : public Base
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
typedef typename Base::ReturnType ReturnType;
|
2003-01-06 02:26:33 +00:00
|
|
|
ReturnType Visit(T&)
|
2003-02-27 15:47:47 +00:00
|
|
|
{}
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
struct NonStrictVisitorUnitWrapper
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
template <class T, class B>
|
|
|
|
struct In
|
|
|
|
{
|
2003-02-27 15:47:47 +00:00
|
|
|
typedef typename B::ReturnType R;
|
|
|
|
typedef typename Select<Private::IsVoid<R>::value,
|
|
|
|
NonStrictVisitorUnitVoid<T, B>,
|
|
|
|
NonStrictVisitorUnit<T, B>
|
|
|
|
>::Result type;
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2003-03-05 23:39:15 +00:00
|
|
|
template <class TList, typename R = Loki::Private::VoidWrap::type>
|
|
|
|
class NonStrictVisitor
|
2003-01-06 02:26:33 +00:00
|
|
|
: public GenLinearHierarchy<
|
2003-03-05 23:39:15 +00:00
|
|
|
TList,
|
|
|
|
NonStrictVisitorUnitWrapper,
|
2003-02-27 15:47:47 +00:00
|
|
|
Visitor<TList, R> >
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template BaseVisitable
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2003-02-27 15:47:47 +00:00
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
template <class R, class CatchAll>
|
|
|
|
class BaseVisitableBase
|
|
|
|
{
|
|
|
|
typedef R ReturnType;
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
template <class T>
|
|
|
|
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
|
|
|
{
|
|
|
|
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
|
|
|
|
// Apply the Acyclic Visitor
|
|
|
|
if (Visitor<T, R>* p = dynamic_cast<Visitor<T, R>*>(&guest))
|
2003-02-27 15:47:47 +00:00
|
|
|
{
|
2003-03-06 13:54:00 +00:00
|
|
|
return p->Visit(visited);
|
2003-02-27 15:47:47 +00:00
|
|
|
}
|
2003-03-06 13:54:00 +00:00
|
|
|
return CatchA::OnUnknownVisitor(visited, guest);
|
|
|
|
}
|
|
|
|
~BaseVisitableBase() {}
|
|
|
|
|
2003-02-27 15:47:47 +00:00
|
|
|
};
|
|
|
|
template <class R, class CatchAll>
|
|
|
|
class BaseVisitableVoidBase
|
|
|
|
{
|
2003-03-05 23:39:15 +00:00
|
|
|
typedef R ReturnType;
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
template <class T>
|
|
|
|
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
|
|
|
{
|
|
|
|
typedef ApplyInnerType2<CatchAll, R, T>::type CatchA;
|
|
|
|
// Apply the Acyclic Visitor
|
|
|
|
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
|
2003-02-27 15:47:47 +00:00
|
|
|
{
|
2003-03-06 13:54:00 +00:00
|
|
|
p->Visit(visited);
|
|
|
|
return;
|
2003-02-27 15:47:47 +00:00
|
|
|
}
|
2003-03-06 13:54:00 +00:00
|
|
|
CatchA::OnUnknownVisitor(visited, guest);
|
|
|
|
}
|
|
|
|
~BaseVisitableVoidBase() {}
|
2003-02-27 15:47:47 +00:00
|
|
|
};
|
|
|
|
}
|
2003-03-05 23:39:15 +00:00
|
|
|
template
|
2003-01-06 02:26:33 +00:00
|
|
|
<
|
2003-03-05 23:39:15 +00:00
|
|
|
typename R = Loki::Private::VoidWrap::type,
|
2003-01-06 02:26:33 +00:00
|
|
|
class CatchAll = DefaultCatchAllWrapper
|
|
|
|
>
|
2003-02-27 15:47:47 +00:00
|
|
|
class BaseVisitable : public Select<Private::IsVoid<R>::value,
|
|
|
|
Private::BaseVisitableVoidBase<R, CatchAll>,
|
|
|
|
Private::BaseVisitableBase<R, CatchAll>
|
|
|
|
>::Result
|
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef R ReturnType;
|
|
|
|
virtual ~BaseVisitable() {}
|
|
|
|
virtual ReturnType Accept(BaseVisitor&) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// macro DEFINE_VISITABLE
|
2003-03-05 23:39:15 +00:00
|
|
|
// Put it in every class that you want to make visitable (in addition to
|
2003-01-06 02:26:33 +00:00
|
|
|
// deriving it from BaseVisitable<R>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#define DEFINE_VISITABLE() \
|
2003-02-27 15:47:47 +00:00
|
|
|
virtual ReturnType Accept(Loki::BaseVisitor& guest) \
|
2003-01-06 02:26:33 +00:00
|
|
|
{ return AcceptImpl(*this, guest); }
|
|
|
|
|
|
|
|
#define DEFINE_VISITABLE_VOID() \
|
2003-02-27 15:47:47 +00:00
|
|
|
virtual ReturnType Accept(Loki::BaseVisitor& guest) \
|
2003-01-06 02:26:33 +00:00
|
|
|
{ AcceptImpl(*this, guest); }
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template CyclicVisitor
|
2003-03-05 23:39:15 +00:00
|
|
|
// Put it in every class that you want to make visitable (in addition to
|
2003-01-06 02:26:33 +00:00
|
|
|
// deriving it from BaseVisitable<R>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2003-02-27 15:47:47 +00:00
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
template <typename R, class TList>
|
|
|
|
class CyclicVisitorBase : public Visitor<TList, R>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
template <class Visited>
|
2003-01-06 02:26:33 +00:00
|
|
|
ReturnType GenericVisit(Visited& host)
|
|
|
|
{
|
|
|
|
Visitor<Visited, ReturnType>& subObj = *this;
|
|
|
|
return subObj.Visit(host);
|
|
|
|
}
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
~CyclicVisitorBase() {}
|
2003-02-27 15:47:47 +00:00
|
|
|
};
|
2003-01-06 02:26:33 +00:00
|
|
|
template <class TList>
|
2003-02-27 15:47:47 +00:00
|
|
|
class CyclicVisitorVoidBase : public Visitor<TList, void>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
template <class Visited>
|
2003-01-06 02:26:33 +00:00
|
|
|
ReturnType GenericVisit(Visited& host)
|
|
|
|
{
|
|
|
|
Visitor<Visited, ReturnType>& subObj = *this;
|
|
|
|
subObj.Visit(host);
|
|
|
|
}
|
2003-03-06 13:54:00 +00:00
|
|
|
protected:
|
|
|
|
~CyclicVisitorVoidBase() {}
|
2003-02-27 15:47:47 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename R, class TList>
|
|
|
|
class CyclicVisitor : public Select<Private::IsVoid<R>::value,
|
|
|
|
Private::CyclicVisitorVoidBase<TList>,
|
|
|
|
Private::CyclicVisitorBase<R, TList>
|
|
|
|
>::Result
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef R ReturnType;
|
|
|
|
// using Visitor<TList, R>::Visit;
|
2003-03-05 23:39:15 +00:00
|
|
|
|
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
};
|
2003-03-05 23:39:15 +00:00
|
|
|
|
2003-01-06 02:26:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// 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
|
2003-03-05 23:39:15 +00:00
|
|
|
// Feb 23, 2003: Removed special visitor classes for return type void.
|
2003-02-27 15:47:47 +00:00
|
|
|
// Added Loki:: qualification to Accept's Paramter (in the macro) B.K.
|
2003-03-06 13:54:00 +00:00
|
|
|
// Mar 06, 2003: Changed default values for return types to void.
|
|
|
|
// Added protected destructors to private implementation classes B.K.
|
2003-01-06 02:26:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#endif // VISITOR_INC_
|
2003-02-27 15:47:47 +00:00
|
|
|
#endif
|