I am trying to implement the visitor pattern for walking an AST. I have defined an ASTNode
which can accept a Visitor
, and will allow the visitor to visit itself. The example below contains one concrete implementation each of the Visitor and the 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;
}
};
Then, I can walk the AST using something like this:
Roman r;
ToStringVisitor tsv;
// ...
return r.accept(tsv, 42);
As you can see, I am trying to use templates to allow for a parameter and return value. However, I get the compiler error:
error: templates may not be 'virtual'
virtual R accept(Visitor<R, P>& v, P p) {
I have a vague understanding of why this is an error. However, how can I accomplish this legally?
Edit: I don't think this is a duplicate of this question, because I'm also trying to have accept return a template type.