📄 visitor.h
字号:
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: Mar 06, 2003
//
// Like the original library, this port now uses void as
// default value for return types.
//
// This new of visitor.h handles void returns transparently. See
// readme.txt for an explanation of the used technique.
// However there are still two sets of macros. One for return type = void
// (DEFINE_VISITABLE_VOID, DEFINE_CYCLIC_VISITABLE_VOID) and one for return
// type != void (DEFINE_VISITABLE, DEFINE_CYCLIC_VISITABLE)
//
// If you prefer the old version of visitor.h which uses a different set of
// visitor classes for the return type void, define the macro
// USE_VISITOR_OLD_VERSION.
//
#ifdef USE_VISITOR_OLD_VERSION
#include "VisitorOld.h"
#else
#ifndef VISITOR_INC_
#define VISITOR_INC_
#include "Typelist.h"
#include "HierarchyGenerators.h"
#include "MSVC6Helpers.h"
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitor
// The base class of any Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
////////////////////////////////////////////////////////////////////////////////
// class template Visitor
// The building block of Acyclic Visitor
////////////////////////////////////////////////////////////////////////////////
template <class T, typename R = Loki::Private::VoidWrap::type >
class Visitor;
////////////////////////////////////////////////////////////////////////////////
// class template Visitor (specialization)
// This specialization is not present in the book. It makes it easier to define
// Visitors for multiple types in a shot by using a typelist. Example:
//
// class SomeVisitor :
// public BaseVisitor // required
// public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,
// public Visitor<Paragraph>
// {
// public:
// void Visit(RasterBitmap&); // visit a RasterBitmap
// void Visit(Paragraph &); // visit a Paragraph
// };
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
// helper for Visitor's the left base class
template <unsigned int ListId>
struct VisitorImplLeft
{
template <class TList, class R>
struct In
{
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
// helper for Visitor's the right base class
template <unsigned int ListId>
struct VisitorImplRight
{
template <class TList, class R>
struct In
{
typedef typename TList::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
// simulates specialization
// class Visitor<Head, R>
template <>
struct VisitorImplLeft<TL::Private::NoneList_ID>
{
template <class T, class R>
struct In
{
struct Result
{
typedef R ReturnType;
virtual ReturnType Visit(T&) = 0;
};
};
};
// simulates the left base class for the specialization
// class Visitor<Typelist<Head, Tail>, R>
template <>
struct VisitorImplLeft<TL::Private::Typelist_ID>
{
template <class TList, class R>
struct In
{
typedef Visitor<typename TList::Head, R> Result;
};
};
template <>
struct VisitorImplRight<TL::Private::NoneList_ID>
{
template <class TList, class R>
struct In
{
struct Result {};
};
};
// simulates the right base class for the specialization
// class Visitor<Typelist<Head, Tail>, R>
template <>
struct VisitorImplRight<TL::Private::Typelist_ID>
{
template <class TList, class R>
struct In
{
typedef Visitor<typename TList::Tail, R> Result;
};
};
template <>
struct VisitorImplRight<TL::Private::AtomList_ID>
{
template <class TList, class R>
struct In
{
struct Result {};
};
};
// MSVC 6.0 will complain if we try to let Visitor inherit
// directly from VisitorImplLeft/VisitorImplRight
template <class T, class R>
struct VisitorImplLeftWrap
{
struct Dummy{};
typedef typename VisitorImplLeft
<
TL::Private::IsTypelist<T>::type_id == TL::Private::AtomList_ID ?
TL::Private::Typelist_ID :
TL::Private::IsTypelist<T>::type_id
>::template In<T, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
template <class T, class R>
struct VisitorImplRightWrap
{
struct Dummy{};
typedef typename VisitorImplRight
<
TL::Private::IsTypelist<T>::type_id
>::template In<T, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
}
template <class T, typename R>
class Visitor : public Private::VisitorImplLeftWrap<T, R>::Result,
public Private::VisitorImplRightWrap<T, R>::Result
{
public:
typedef R ReturnType;
};
////////////////////////////////////////////////////////////////////////////////
// class template BaseVisitorImpl
// Implements non-strict visitation (you can implement only part of the Visit
// functions)
////////////////////////////////////////////////////////////////////////////////
template <class TList, typename R = Loki::Private::VoidWrap::type >
class BaseVisitorImpl;
namespace Private
{
template <unsigned int ListTag>
struct BaseVisitorImplHelper
{
template <typename T, typename R>
struct In
{
typedef typename T::ERROR_WRONG_SPECIALIZATION_SELECTED Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::Private::Typelist_ID>
{
template <typename TList, typename R>
struct In
{
typedef BaseVisitorImpl<TList, R> Result;
};
};
template<>
struct BaseVisitorImplHelper<TL::Private::NullType_ID>
{
template <typename TList, typename R>
struct In
{
struct Result {};
};
};
template <class T, class R>
struct BaseVisitorImplWrap
{
struct Dummy {};
typedef typename BaseVisitorImplHelper
<
TL::Private::IsTypelist<typename T::Tail>::
type_id == TL::Private::AtomList_ID ?
TL::Private::Typelist_ID :
TL::Private::IsTypelist<typename T::Tail>::type_id
>::template In<typename T::Tail, R>::Result TempType;
typedef VC_Base_Workaround<TempType, Dummy> Workaround;
typedef Workaround::LeftBase Result;
};
template <class TList, class R>
struct BaseVisitorImplBase : public Visitor<typename TList::Head, R>,
public Private::BaseVisitorImplWrap<TList, R>::Result
{
ASSERT_TYPELIST(TList);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -