访客实施:持续与可变访问者

时间:2013-12-14 18:55:22

标签: c++ inheritance visitor const-correctness

鉴于常量访问者和可变访问者之间的区别在于,不允许常量访问者中的方法修改访问对象。

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
  3. 的方法

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

    编辑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语句 另一种方法是从数据库表中加载字段。

1 个答案:

答案 0 :(得分:0)

  

有没有办法使用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;