In addition to the Gang of Four visiter there is yet another completely separate kind of visitor called
NSI click visitor now and a cyclic visitor is different.
You see we have our conventional cyclic visiter which is based on function overloading as you probably
remember what happens is the visitor basically overloads the visit function for whatever type it visits.
But this really only works if you have a stable hierarchy where you have some sort of inheritance approach
to enforce the presence of the except method.
There is a completely different way of doing things and that is the cyclic visiter which is based on
RTTY unfortunately and as a consequence it is significantly slower but it does have its own benefits.
For example it doesn't put any limitations on us in terms of hierarchies so let's take a look at how
you can implement the cyclic visitor.
So first of all we're going to define an interface for a visitor.
So I'm going to have templates type name visitable struct visiter and this is just going to have a single
virtual function called visit.
And what we do here is we specify that we can visit some visitable so we can visit whatever this object
happens to be.
You'll notice that we're doing very generic kind of programming here.
Now what we do is we introduce a marker interface called visiter base.
So this is an interface which is really going to have much now we can't leave it empty unfortunately
because we need the tables to be constructed so we're going to add something here.
We're going to add a virtual destructor.
So let's just add a default implementation of a virtual these structure and that's our marker interface
so it doesn't really have a new thing inside itself.
But we are going to be using it in order to actually accept this Moktar interface as an argument in
the accept method.
So coming back to our examples where we had expressions and we had addition expressions as well as double
expressions that was actually defined a base class once again.
So here is the base class called expression.
I'll add some sort of virtue on the structure here.
Just for the fun of it.
But the really interesting thing is the accept method so we're going to have a method called accept
which is going to accept a reference to visitor base.
OK so what's going on here.
Well we're accepting some marker interface that you can subsequently use to indicate that the argument
can be accepted by an expression for example.
Now here is the interesting part.
And this is going to get a bit complicated I'm afraid.
So what we really want is we want to make sure that the visitor base that we have that would be the
the object here we want to make sure that this object here is actually the off type visitor with a particular
type T and that type T this type T has to correspond to our current type.
In this case it's expression.
So the way this is done is of course by using a dynamic cast so I'm going to make a using here so I'm
going to define an expression visitor as a visitor of expressions like so.
So let's just say using just a shorthand type effectively and then I'm going to say the following.
If Auto V equals dynamic cast TV star RBJ then what we're going to do is we're going to take Eevee and
that's a point here and we're going to call visit on it with a reference to ourselves.
So this might seem like really cryptic kind of C++.
I mean what's going on here.
So the idea is that we accept a visitor in a very helpful way.
And the very kind of careful measured way in so far as we verify the visitor base that were being passed
inside the accept method is of the type that knows how to accept an expression specifically.
That's why we're using visiter off type expression so this type here type visitable basically tells
you that you can except this particular type of expression.
OK so let's continue with our implementation and that's implemented double expression as well as addition
expression like we had before.
So double expression is an expression.
There we go.
So we'll have the value and then we'll have the constructor that initializes this value.
But apart from that we now need to have an accept method once again.
So we're going to have a virtual void except and in actual fact the implementation of Except here is
very similar to the implementation of Except that we have here.
So let me just copy this and paste it here.
So we have yet another implementation of access but this one is different.
This one is different because what happens here is we want a visitor for a double expression.
So we can have a double expression here and I may as well rename this to.
Let's see the double expression visitor.
There we go.
But the implementation is pretty much the same.
So we get a visitor.
We verify that the visitor can actually visit our particular type that it is in fact off type visit
or double expression.
And if it is we have a valid pointer here and we use that pointer to perform the actual visit.
OK so finally the addition expression once again an additional expression which happens to be an expression
like so and then I will have the members so left and right.
Will have to have a constructor which actually initializes both of them.
Now remember in the original example we also had a destructor meaning that the addition expression actually
owns its children.
So we're going to have the destructor for of expression which deletes the left and deletes the right
as well.
And finally we need the accept method once again so here it is another except and this time round we
have a bit of addition expression and I'm going to once again rename this to a different expression.
Visitor A.
So we now have every single element in the hierarchy having it's own except.
And this excerpt can in fact accept a visitor.
In actual fact Now one interesting thing you're going to note is that strictly speaking they are all
kind of just just ordinary virtual methods meaning that we don't have expression as a kind of base class
where this is pure virtue and you absolutely must implement this in the in the heritage.
This is actually something that's going to be visible in our example.
OK so what we want to do now is want to reconstruct the expression printer and now things are going
to be really interesting because the expression printer is going to be expressed in a completely different
way so we're going to implement visitor base.
Now remember visitor base is just a marker interface.
It doesn't have anything but it allows us to work our way into every single accept method that any kind
of expression actually has.
Because we all take a visitor base and we are visitor base so we can now be accepted by anyone who might
be interested.
But in addition we want to specify the kind of expressions that we can visit.
So for example I can say that I'm an visitor of double expression and also a visitor of addition expression.
OK so if I do it like this let's see what's going on here.
So obviously I need to implement not just one visit method but I need to implement several.
So if you go into the generate menu and implement functions you're going to get them one after another.
So first of all you can see that we're getting it for double expression let's press return here but
no we go and do it again we go and implement functions once again and this time round we get it for
an addition expression.
So we have two of these overloads which actually while they're not there they are overloads but they
are overloads predicated by our inheritance specification so we can visit.
In addition expression then we can visit a double expression as well so once again all I would do here
is I would have some sort of private section where you would have an o string stream and then here we
can actually populate it so in the case of double expression that would be first.
This is actually easy because all we do is we add the actual object value to the stream.
And in the action expression that's where we do predictable things so we add the opening round brackets.
And then what we do is we take the object which take the left side of the object and we call except
on that.
So you'll notice the once again except takes a visit or base but we are inside a visitor base so we
can just feed store this in there to accept the current visitor.
Then we had the plus operator then we do.
All right except start this and then finally we do s.
So we put in the closing bracket.
OK so this is our implementation of the expression printer.
We can actually start using it so we can go down here and we can do the same kind of definition that
we had previously meaning something like this one plus two plus three.
And we can try printing it so we can make an expression printer EPM and I can see EPEAT visit and pass.
And just a reference to the current expression so that would be actually ampersand e because remember
e itself is a pointer it's initialized with the news so it's a pointer.
And we all we kind of implement it like so now you'll notice that there is a red underline here say
no matching function.
Now if we actually specify the time I believe you can do this using a line well I would hope that you
would be able to do it using C line but I think I think we are actually OK.
I think that we're OK in terms of it's just not ampersand because that would be taking the address of
a pointer it's a star.
He you have to dereference the pointer.
So we're OK here we can visit this expression and we can print out the result.
So for printing out the result once again I'm going to make a public member here.
String here which returns o s s s t like so.
So that's what we're going to be printing here.
I'm going to say you know SDR.
Let's put a line break at the end of it.
All right so we have our example we can run it and see what we actually get.
All right so as you can see we're getting the same kind of output that we were getting previously but
we are getting it in a slightly different way.
So you're probably wondering well hold on what is exactly the advantage of this kind of approach.
Well imagine that you have elements which are not themselves expressions and you also want them to be
visitable somehow.
Now you don't have to start building a rigid hierarchy where every single construct has this except
a because that double jump that we did and the set of overloads in the different visitors was mandatory.
You are absolutely had to have a visit.
Now let me show you what happens here what happens here is I can get rid of this visitor.
I can get rid of it completely.
I can take this whole function I can comment it out and guess what.
The example that we've just built continues to work except obviously it's going to print the numbers
it will print the round brackets and the pluses and whatnot but it's going to continue to work.
Or it might.
Let's actually build this let's see what we get here.
All right so as you can see it's compiled and we can actually run this and see what the output is.
And as you can see all that happened here is we are not printing the expressions anymore we're just
printing the pluses and the brackets.
So this kind of approach essentially gives you additional flexibility because instead of digging everything
into one single rigid hierarchy that becomes reasonably costly to augment.
You can go more slowly about expanding your example and incorporating additional elements because what's
happening here essentially is when you call except on these two things.
What's happening is well sure you are figuring out what kind of element actually has the except method.
But let's imagine that you're getting yourself into a double expression let's suppose that OBB the left
is a double expression so you call except on it and you end up in here you end up in this except now
you're trying to cast it to a visitor of a double expression but you cannot because remember we just
commented out this particular inheritance member.
And so nothing happens.
It's effectively a no.
And this is just a small illustration of a simple implementation of the cyclic visiter because you can
suddenly have a much more complicated setup here.