3

I've currently trouble implementing the Visitor-Pattern in a Header-Only library in C++.

Consider following class which should support being visited by a visitor (no interface for simplicity reasions):

class Acceptor
{
    void accept(Visitor* v)
    {
        v->visit(this);
    }
};

Here is the interface for the visitors:

class Visitor
{
    virtual void visit(Acceptor* t) = 0;
};

In a Header-Only lib, Acceptor.hpp must include Visitor.hpp and Visitor.hpp must include Acceptor.hpp. Since both headers are protected by Include-Guards, the later one will fail. Using forward declarations won't solve the problem, too.

Bastian
  • 1,553
  • 13
  • 33
  • 2
    For `Visitor` an incomplete type of `Acceptor` (aka `class Acceptor;`) is sufficient. Hence, you can break the cyclic `#include`s by including `Visitor` in `Acceptor` but not vice versa. – Scheff's Cat Nov 04 '19 at 15:05

1 Answers1

4

For Visitor an incomplete type of Acceptor (aka class Acceptor;) is sufficient. Hence, you can break the cyclic #includes by including Visitor in Acceptor but not vice versa.

To demonstrate this, I made a one-file-MCVE:

class Acceptor;

class Visitor
{
    friend class Acceptor;

    virtual void visit(Acceptor* t) = 0;
};

class Acceptor
{
    void accept(Visitor* v)
    {
        v->visit(this);
    }
};

Live Demo on coliru

Note:

I had to add the friend class Acceptor because all member functions of OPs code are private. However, even for this the incomplete type class Acceptor appears sufficient.


With separate files:

File visitor.h:

#ifndef VISITOR_H
#define VISITOR_H

class Acceptor;

class Visitor
{
    friend class Acceptor;

    virtual void visit(Acceptor* t) = 0;
};

#endif // VISITOR_H

File acceptor.h:

#ifndef ACCEPTOR_H
#define ACCEPTOR_H

#include "visitor.h"

class Acceptor
{
    void accept(Visitor* v)
    {
        v->visit(this);
    }
};

#endif // ACCEPTOR_H
Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • Thank you very much! I've just realized that my problem was, that I didn't created a separate .hpp file for the visitor interface. – Bastian Nov 04 '19 at 15:38