【发布时间】:2017-08-18 05:42:00
【问题描述】:
我正在尝试实现访问 AST 的访问者模式。我定义了一个ASTNode,它可以接受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 的重复,因为我也在尝试让接受返回模板类型。
【问题讨论】:
-
visitor-pattern-example-in-c++ 展示了如何在访问者中设置返回类型,您可以对额外参数执行相同操作。
标签: c++ templates design-patterns abstract-syntax-tree visitor-pattern