访问者实现:恒定访问者与可变访问者

Visitor Implementation: Constant versus Mutable Visitor

本文关键字:访问者 实现      更新时间:2023-10-16

给定常量访问者和可变访客之间的区别是常量访问者中的方法不允许修改访问的对象。

class Integer_Field;
class Boolean_Field;
class Text_Field;
class Visitor_Constant
{
  public:
    virtual void visit(const Integer_Field& f) = 0;
    virtual void visit(const Boolean_Field& f) = 0;
    virtual void visit(const Text_Field& f) = 0;
};
class Visitor_Mutable
{
  public:
    virtual void visit(Integer_Field& f) = 0;
    virtual void visit(Boolean_Field& f) = 0;
    virtual void visit(Text_Field& f) = 0;
};

我想尽量减少对这些来访者的支持。例如,如果我提出一个类Blob_Field,我需要修改这两个类。我更喜欢只需要修改一个类或模具的东西。

当从这些父访问者中定义了许多类时,维护问题就会加剧。这是我想简化维护的主要原因。

我的问题:
(注意:这必须在不使用C++11功能的情况下解决,因为我的开发环境不支持C++11,而且我现在不允许升级。)

  1. 有没有办法使用template机制将两者合并(例如将"const"作为参数提供给模板)
  2. 我如何安排这些访客,以便通过Visitor_Constant到使用Visitor_Mutable

注意:通过父类组合这些类,会使必须实现和维护的访问者方法加倍

编辑1:类关系

class Component; // Base class for fields and records.
class Field : public Component; // Base class for all fields
class Record : public Component // Base class for all records
{
  std::vector< boost::shared_ptr<Component> > component_container;
};
class Integer_Field : public Field;
class Boolean_Field : public Field;
class Text_Field : public Field;

编辑2:字段的合理性
被专门处理的字段的一个合理性是生成用于创建表的SQL语句
另一个是从数据库表加载字段。

有没有办法使用template机制来合并两者(例如将"const"作为模板的参数)?

您可以通过模板模板参数提供它,也可以保持纯访问者实现的通用性。我最初是在C++11中完成的,但既然你说你没有,我就用类型列表来代替它。

这是类型列表实现。

/* Our empty node for our type list. */
class Empty {};
/* Cons for our type list. */
template <typename First_, typename Rest_>
class Cons {
  public:
  /* First type */
  typedef First_ First;
  /* Rest.  */
  typedef Rest_ Rest;
};  // Cons<First_, Rest_>

以下是通用访问者实现。

/* Forward declaration. */
template <template <typename> class Decorator, typename Members>
class VisitorRecur;
/* Base case. */
template <template <typename> class Decorator, typename Member>
class VisitorRecur<Decorator, Cons<Member, Empty> > {
  public:
  /* Pure virtual for each of the members. */
  virtual void operator()(
      typename Decorator<Member>::Type that) const = 0;
};  // VisitorRecur<Decorator, Member>
/* Recursive case. */
template <template <typename> class Decorator, typename Members>
class VisitorRecur
    : public VisitorRecur<Decorator, typename Members::Rest> {
  public:
  /* Bring the operator()s into scope. */
  using VisitorRecur<Decorator, typename Members::Rest>::operator();
  /* Pure virtual for each of the members. */
  virtual void operator()(
      typename Decorator<typename Members::First>::Type that) const = 0;
};  // VisitorRecur<Decorator, typename Members::Rest>
/* Final visitor. */
template <template <typename> class Decorator, typename Members>
class Visitor : public VisitorRecur<Decorator, Members> {
  public:
  /* Bring the operator()s into scope. */
  using VisitorRecur<Decorator, Members>::operator();
};  // Visitor<Decorator, Members>

以下是我们将定义的两个装饰器。

/* ConstRef. */
template <typename T>
class ConstRef {
  public:
  typedef const T & Type;
};  // ConstRef<T>
/* Ref. */
template <typename T>
class Ref {
  public:
  typedef T & Type;
};  // Ref<T>

这是它的用例。

/* Forward declarations. */
class Circle;
class Square;
class Triangle;
/* Add the members into a type list. */
typedef Cons<Circle, Cons<Square, Cons<Triangle, Empty> > > Members;
/* Our const visitor which accepts the members by const-ref. */
typedef Visitor<ConstRef, Members> ConstVisitor;
/* Our mutating visitor which accepts the members by ref. */
typedef Visitor<Ref, Members> MutatingVisitor;