Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8714865
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T05:42:23+00:00 2026-06-13T05:42:23+00:00

PLEASE NOTE: These are code snippets depicting the general dilemma. The complete code DOES

  • 0

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?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T05:42:24+00:00Added an answer on June 13, 2026 at 5:42 am

    Yes, there is a way to do this in C++. You need to use forward declarations and, if required, split declarations and definitions. Here is an example (please read comments for explanation):

    #include <cstdio>
    #include <string>
    
    /// --- A.hpp ---
    
    // First, you have to forward declare a visitor type.
    class Visitor;
    
    // Then declare/define a node base class (interface).
    class Node {
      public:
        Node() {}
        virtual ~Node() {}
    
        // Note that Visitor, as a type, is referenced here, but none of its
        // "body" is used, so forward declaration is enough for us.
        virtual void accept(Visitor & v) = 0;
    };
    
    /// --- B.hpp (includes A.hpp) ---
    
    // Then, to declare the actual interface for a visitor, we must play the same
    // trick with forward declaration, but for specific node types:
    class NodeA;
    class NodeB;
    
    // And once those types are "pre-declared", declare visitor interface.
    class Visitor {
      public:
        Visitor() {}
        virtual ~Visitor() {}
    
        virtual void visit(const Node & node);
        virtual void visit(const NodeA & node);
        virtual void visit(const NodeB & node);
    };
    
    /// --- C.hpp (includes B.hpp) ---
    
    // Once visitor is declared, declare/define specific nodes.
    class NodeA : public Node {
      public:
        std::string node_name;
    
        NodeA() : node_name("I am a node of type A!") {}
        virtual ~NodeA() {}
        virtual void accept(Visitor & v) { v.visit(*this); }
    };
    
    class NodeB : public Node {
      public:
        std::string node_name;
    
        NodeB() : node_name("B node here!") {}
        virtual ~NodeB() {}
        virtual void accept(Visitor & v) { v.visit(*this); }
    };
    
    // --- B.cpp (includes B.hpp and C.hpp) ---
    
    // Now, nodes are declared, so that we can define visitor's methods.
    // Note that if you don't need to use "node" parameters, this can
    // as well go with declaration and there is no need to "define" this later.
    void Visitor::visit(const Node & node) {
        printf("Base visitor got base node\n");
    }
    
    void Visitor::visit(const NodeA & node) {
        printf("Base visitor got node A\n");
    }
    
    void Visitor::visit(const NodeB & node) {
        printf("Base visitor got node B\n");
    }
    
    // --- YourProgram.[cpp|hpp] includes at most C.hpp --
    
    // Than, at any point in your program, you can have a specific visitor:
    class MyVisitor : public Visitor {
      public:
        MyVisitor() {}
        virtual ~MyVisitor() {}
    
        virtual void visit(const Node & node) {
            printf("Got base node...\n");
        }
    
        virtual void visit(const NodeA & node) {
            printf("Got %s\n", node.node_name.c_str());
        }
    
        virtual void visit(const NodeB & node) {
            printf("Got %s\n", node.node_name.c_str());
        }
    };
    
    // And everything can be used like this, for example:
    int main()
    {
        Visitor generic_visitor;
        MyVisitor my_visitor;
    
        NodeA().accept(generic_visitor);
        NodeA().accept(my_visitor);
        NodeB().accept(generic_visitor);
        NodeB().accept(my_visitor);
    }
    

    … and by the way, don’t forget to use include guards or else you may end up including the same file multiple times which will result in a lot of errors.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

The following code works perfectly in non-IE browsers. Please note that these first three
I want to perform simple validation against multiple fields. Please note these fields are
PLEASE NOTE: This is a CODE QUESTION NOT AN SYSTEM MANIPULATION ONE. I have
Please note this application will never be running on a server system. I am
Please note that I'm not asking how but why. And I don't know if
[Please note that this is a different question from the already answered How to
(Please note that I have seen a similar question on StackOverflow recently, however I
Please note: This is a question about the Eclipse plugin Subversive , and not
Please note this is not a question about online/hosted SVN services. I am working
Please note that this is not homework and i did search before starting this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.