c++ - 虚拟模板函数: implementing the Visitor pattern with parameters

标签 c++ templates design-patterns abstract-syntax-tree visitor-pattern

我正在尝试实现访问 AST 的访问者模式。我定义了一个ASTNode,它可以接受Visitor,并允许访问者访问自身。下面的示例包含 Visitor 和 ASTNode 各一个具体实现。

class ASTNode;

template <class P, class R>
class Visitor {
    public:
        virtual ~Visitor() {}
        virtual R visit(ASTNode& node, P p) const = 0;
};

class ASTNode {
    public:
        virtual ~ASTNode() {}
        template <class P, class R>
        virtual R accept(Visitor<R, P>& v, P p) {
            return v.visit(*this);
        }
};

class Roman : public ASTNode {
    public:
        Roman(Numeral n, optional<Accidental> a) : numeral(n), alteration(a) {};
        const Numeral numeral;
        const optional<Accidental> alteration;
};

class ToStringVisitor : public Visitor<string, int> {
    virtual string visit(Roman& node, int param) {
        string result = NumeralStrings[node.numeral];
        if (node.alteration.has_value()) result = accidentalToString(node.alteration.value()) + result;
        return result;
    }
};

然后,我可以使用如下方式遍历 AST:

Roman r;
ToStringVisitor tsv;
// ...
return r.accept(tsv, 42);

正如您所看到的,我正在尝试使用模板来允许参数和返回值。但是,我收到编译器错误:

 error: templates may not be 'virtual'
       virtual R accept(Visitor<R, P>& v, P p) {

我对为什么这是一个错误有一个模糊的理解。但是,我怎样才能合法地实现这一点呢?

编辑:我认为这不是 this question 的重复项,因为我还尝试让accept返回模板类型。

最佳答案

访问/接受函数不应接受额外参数或返回 void 以外的任何内容。具体访问者对象在构造时获取额外的数据。它还可以存储您想要从方法返回的任何结果。这是沼泽标准构造,不需要任何模板。

  class NodeVisitor {
      virtual void visit (Roman*) = 0;
      ...
  };

  class ToStringVisitor : public NodeVisitor {
      ToStringVisitor (int param) : param(param) {}
      void visit (Roman* r) {
          result = ...;
      }
      ...
      int param;
      std::string result;
  };

关于c++ - 虚拟模板函数: implementing the Visitor pattern with parameters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45749266/

相关文章:

c++ - 如何从 Windows 服务启动系统帐户下的单独进程?

c++ - 是否可以重载模板函数以与 std::vector 的元素一起使用?

c# - 我需要继承两个类(这在 C# 中是不可能的)任何人都可以推荐一种不同的方法吗?

c++ - 如何让 ss << f 像 printf ("%g", f) 一样工作;

c++ - 停止增加的无限递归模板实例化,这是不需要的

c++ - 最好是更新一个小的顶点缓冲区,还是发送一个制服?

c++ - 为什么优化标志会导致某些模板函数的链接器错误?

c++ - 使用不完整类型的函数模板实例化

java - 这是Monster Builder的一个很好的Builder/Factory模式,用于抽象混合有setter的长构造函数吗?

javascript - AngularJS 设计模式 : Should I use factories to create constructor functions?