PLEASE NOTE: These are code snippets depicting the general dilemma. The complete code DOES include "include guards" / #pragma once / whathaveyou.
I'm implementing the visitor pattern for traversing an AST and wondering what's the C++ way to solve the following:
I have AST.h which has the base AST node class declaration:
class Node
{
public:
virtual void accept(Visitor* v) {v->visit(this);}
};
Along with all concrete node subclasses for declarations, expressions,etc..
And then I have ASTVisitor.h which declares the visitor interface, along the lines of:
class Visitor
{
public:
Visitor() {}
virtual ~Visitor() {}
virtual void visit(StringElement* e) {}
virtual void visit(RealElement* e) {}
virtual void visit(IntegerElement* e) {}
...
The problem is, AST.h needs ASTVisitor.h so that the accept method knows that Visitor objects have a visit method. That is, so that both Visitor and visit() are declared for virtual void accept(Visitor* v) {v->visit(this);}
. But at the same time, ASTVisitor.h needs AST.h so that the Visitor class knows that all concrete subclasses of Node exist. That is, so that, for instance, StringElement is declared for the signature in virtual void visit(StringElement* e)
But including ASTVisitor.h in AST.h and AST.h in ASTVisitor.h results in the Visitor class not being "seen" by the Node class and therefore, not being valid as a type for accept's parameter. Also, doing a forward declaration, like class Visitor;
in AST.h only solves the type problem for the method signature, but inside the method v->visit(this)
is still invalid since the forward declaration says nothing about the methods for the Visitor class.
So what's the C++ way of solving this?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With