Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

Pohl's law: Nothing is so good that somebody, somewhere, will not hate it.


devel / comp.lang.c++ / What is visitor pattern?

SubjectAuthor
* What is visitor pattern?wij
+* Re: What is visitor pattern?Öö Tiib
|+- Re: What is visitor pattern?wij
|`* Re: What is visitor pattern?wij
| `* Re: What is visitor pattern?Öö Tiib
|  `- Re: What is visitor pattern?wij
+* Re: What is visitor pattern?Pavel
|+* Re: What is visitor pattern?Öö Tiib
||`* Re: What is visitor pattern?Pavel
|| `* Re: What is visitor pattern?Öö Tiib
||  +* Re: What is visitor pattern?Muttley
||  |`* Re: What is visitor pattern?Öö Tiib
||  | `* Re: What is visitor pattern?Tim Rentsch
||  |  `* Re: What is visitor pattern?Öö Tiib
||  |   `- Re: What is visitor pattern?Tim Rentsch
||  `* Re: What is visitor pattern?Pavel
||   `* Re: What is visitor pattern?Öö Tiib
||    `* Re: What is visitor pattern?Pavel
||     `* Re: What is visitor pattern?Öö Tiib
||      `* Re: What is visitor pattern?Pavel
||       `* Re: What is visitor pattern?Öö Tiib
||        `- Re: What is visitor pattern?Pavel
|`* Re: What is visitor pattern?Bonita Montero
| `* Re: What is visitor pattern?Pavel
|  `* Re: What is visitor pattern?Bonita Montero
|   `* Re: What is visitor pattern?Pavel
|    `* Re: What is visitor pattern?Bonita Montero
|     `* Re: What is visitor pattern?Pavel
|      `* Re: What is visitor pattern?Bonita Montero
|       `* Re: What is visitor pattern?Pavel
|        `* Re: What is visitor pattern?Bonita Montero
|         `* Re: What is visitor pattern?Pavel
|          `* Re: What is visitor pattern?Bonita Montero
|           +* Re: What is visitor pattern?Muttley
|           |`* Re: What is visitor pattern?Bonita Montero
|           | `* Re: What is visitor pattern?Muttley
|           |  +* Re: What is visitor pattern?Bonita Montero
|           |  |`* Re: What is visitor pattern?Muttley
|           |  | +* Re: What is visitor pattern?Bonita Montero
|           |  | |`* Re: What is visitor pattern?Muttley
|           |  | | `- Re: What is visitor pattern?Bonita Montero
|           |  | `- Re: What is visitor pattern?Bonita Montero
|           |  `- Re: What is visitor pattern?Pavel
|           `* Re: What is visitor pattern?Pavel
|            `* Re: What is visitor pattern?Bonita Montero
|             `- Re: What is visitor pattern?Pavel
+* Re: What is visitor pattern?Alf P. Steinbach
|`- Re: What is visitor pattern?Alf P. Steinbach
+* Re: What is visitor pattern?Michael S
|+- Re: What is visitor pattern?Bonita Montero
|+- Re: What is visitor pattern?Öö Tiib
|`- Re: What is visitor pattern?Pavel
`- Re: What is visitor pattern?Bonita Montero

Pages:123
What is visitor pattern?

<331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1087&group=comp.lang.c%2B%2B#1087

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:620a:8787:b0:765:942d:b19 with SMTP id py7-20020a05620a878700b00765942d0b19mr21328qkn.13.1692539747579;
Sun, 20 Aug 2023 06:55:47 -0700 (PDT)
X-Received: by 2002:a17:90b:611:b0:26d:15cf:39dc with SMTP id
gb17-20020a17090b061100b0026d15cf39dcmr1134444pjb.0.1692539747030; Sun, 20
Aug 2023 06:55:47 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Sun, 20 Aug 2023 06:55:46 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=124.218.76.41; posting-account=0Ek0TQoAAAAS0oceh95IuNV59QuIWNeN
NNTP-Posting-Host: 124.218.76.41
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
Subject: What is visitor pattern?
From: wyniijj5@gmail.com (wij)
Injection-Date: Sun, 20 Aug 2023 13:55:47 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1261
 by: wij - Sun, 20 Aug 2023 13:55 UTC

I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
but I still don't understand what it tries to say and the example code don't compile.
Can anyone explain the visitor pattern or better webpages?
probably making the example compile may help, thanks in advance.

Re: What is visitor pattern?

<ea1ee058-e460-4e34-a001-4e9375f1a7can@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1088&group=comp.lang.c%2B%2B#1088

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:620a:198a:b0:76c:deff:8c42 with SMTP id bm10-20020a05620a198a00b0076cdeff8c42mr27348qkb.14.1692541359927;
Sun, 20 Aug 2023 07:22:39 -0700 (PDT)
X-Received: by 2002:a63:6d83:0:b0:566:2d6:f720 with SMTP id
i125-20020a636d83000000b0056602d6f720mr691545pgc.7.1692541359504; Sun, 20 Aug
2023 07:22:39 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Sun, 20 Aug 2023 07:22:38 -0700 (PDT)
In-Reply-To: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=84.50.190.130; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 84.50.190.130
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <ea1ee058-e460-4e34-a001-4e9375f1a7can@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Sun, 20 Aug 2023 14:22:39 +0000
Content-Type: text/plain; charset="UTF-8"
 by: Öö Tiib - Sun, 20 Aug 2023 14:22 UTC

On Sunday, 20 August 2023 at 16:55:56 UTC+3, wij wrote:
> I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
> but I still don't understand what it tries to say and the example code don't compile.

Racoon with buzzsaw indicates self-irony.
Example that does not compile is smelly ... OTOH it perhaps just lacks #includes.

#include <array>
#include <iostream>
#include <string>

> Can anyone explain the visitor pattern or better webpages?

Maybe wikipedia?
<https://en.wikipedia.org/wiki/Visitor_pattern>

> probably making the example compile may help, thanks in advance.

Unsure ... people's mind does not grasp double dispatch too well.

Re: What is visitor pattern?

<uIsEM.123835$QQFb.6082@fx38.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1089&group=comp.lang.c%2B%2B#1089

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx38.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Lines: 78
Message-ID: <uIsEM.123835$QQFb.6082@fx38.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Sun, 20 Aug 2023 18:12:42 UTC
Date: Sun, 20 Aug 2023 14:12:42 -0400
X-Received-Bytes: 3799
 by: Pavel - Sun, 20 Aug 2023 18:12 UTC

wij wrote:
> I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
> but I still don't understand what it tries to say and the example code don't compile.
> Can anyone explain the visitor pattern or better webpages?
> probably making the example compile may help, thanks in advance.
>
This seems better than Wikipedia:

https://www.gofpattern.com/behavioral/patterns/visitor-pattern.php

Still I think both are slightly over-complicated / non-focused in how
they describe the original problem.

I would describe it follows:

PROBLEM

1. You have a collection or a stream of objects of different types thru
which you can iterate. Given [a ref to] any such object, you are able to
compute its type and/or call a virtual method.
2. You want to iterate thru these objects and do some op1 with each of
them. Op1 depends on the object type (whole or part of this dependency
could be expressible by only calling virtual method(s) on a [ref to]
common base type).
3. You will likely need to implement other similar operations, say, op2,
op3 etc

OO SOLUTION

1. Ensure all objects have a common base class
2. Add op1 (and later op2...) as a virtual method at the base class and
implement it in all most derived classes (or, if you are lucky, there
will be already some internal nodes in the hierarchy where you can plant
common logic for close siblings -- or you have to expand the hierarchy
to add such internal nodes)

OO SOLUTION analysis

Advantage: all dispatching is done for you by virtual method machinery
Drawback: need to change lots of classes every time you add one op, even
if you could implement op1,op2... using only public API of the object
type (maybe there are not many differences between how the op should
behave on the objects of all those many derived classes (but there are
some)).

VISITOR SOLUTION

1. Ensure all objects have a common base class (say, it's B)
2. create an abstract class Visitor with an abstract method doOp with an
arg of type [ref to] B.
3. add a single method to B, e.g. acceptVisit that takes [ref to]
Visitor and calls doOp on it. NOTE: only one such method is needed, no
matter how many ops you are adding.
4. for every op, create a derived class of Visitor (e.g. Op1Visitor,
Op2Visitor) e.g. and implement doOp() method.

VISITOR SOLUTION analysis:

Advantages:
1. For every new op, you have to add only one class with one virtual method
2. All logic pertaining to the new op is in one place (doOp method).
Drawbacks:
1. There could be need in some dispatching logic in doOp() method
2. All doOp() methods may have to change if a new type is added

EXAMPLE

Enhance formatting of an XML document by adding a red border around the
current depiction of only some elements, depending on the element type.

CONCLUSION

Consider using Visitor when the hierarchy of object types is stable and
an op to add is not a natural extension of the type API that you would
want to implement anyway.

HTH
-Pavel

Re: What is visitor pattern?

<6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1090&group=comp.lang.c%2B%2B#1090

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:622a:6f0a:b0:407:2c52:2861 with SMTP id iv10-20020a05622a6f0a00b004072c522861mr24720qtb.8.1692563681038;
Sun, 20 Aug 2023 13:34:41 -0700 (PDT)
X-Received: by 2002:a05:6a00:b87:b0:687:26bc:6377 with SMTP id
g7-20020a056a000b8700b0068726bc6377mr2882635pfj.3.1692563680755; Sun, 20 Aug
2023 13:34:40 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Sun, 20 Aug 2023 13:34:39 -0700 (PDT)
In-Reply-To: <uIsEM.123835$QQFb.6082@fx38.iad>
Injection-Info: google-groups.googlegroups.com; posting-host=145.14.19.203; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 145.14.19.203
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com> <uIsEM.123835$QQFb.6082@fx38.iad>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Sun, 20 Aug 2023 20:34:41 +0000
Content-Type: text/plain; charset="UTF-8"
 by: Öö Tiib - Sun, 20 Aug 2023 20:34 UTC

On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
> wij wrote:
> > I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
> > but I still don't understand what it tries to say and the example code don't compile.
> > Can anyone explain the visitor pattern or better webpages?
> > probably making the example compile may help, thanks in advance.
> >
> This seems better than Wikipedia:
>
> https://www.gofpattern.com/behavioral/patterns/visitor-pattern.php
>
> Still I think both are slightly over-complicated / non-focused in how
> they describe the original problem.
>
> I would describe it follows:
>
> PROBLEM
>
> 1. You have a collection or a stream of objects of different types thru
> which you can iterate. Given [a ref to] any such object, you are able to
> compute its type and/or call a virtual method.
> 2. You want to iterate thru these objects and do some op1 with each of
> them. Op1 depends on the object type (whole or part of this dependency
> could be expressible by only calling virtual method(s) on a [ref to]
> common base type).
> 3. You will likely need to implement other similar operations, say, op2,
> op3 etc
>
> OO SOLUTION
>
> 1. Ensure all objects have a common base class
> 2. Add op1 (and later op2...) as a virtual method at the base class and
> implement it in all most derived classes (or, if you are lucky, there
> will be already some internal nodes in the hierarchy where you can plant
> common logic for close siblings -- or you have to expand the hierarchy
> to add such internal nodes)
>
> OO SOLUTION analysis
>
> Advantage: all dispatching is done for you by virtual method machinery
> Drawback: need to change lots of classes every time you add one op, even
> if you could implement op1,op2... using only public API of the object
> type (maybe there are not many differences between how the op should
> behave on the objects of all those many derived classes (but there are
> some)).
>
> VISITOR SOLUTION
>

That is illustration of why I said "people's mind does not grasp double
dispatch too well."

> 1. Ensure all objects have a common base class (say, it's B)

Not needed.

> 2. create an abstract class Visitor with an abstract method doOp with an
> arg of type [ref to] B.

Nope, pile of overloads of doOp one for each type processed. Otherwise
how you process different types differently?

> 3. add a single method to B, e.g. acceptVisit that takes [ref to]
> Visitor and calls doOp on it. NOTE: only one such method is needed, no
> matter how many ops you are adding.

Not enough. Every type processed has to have that copy-paste
acceptVisit method. Otherwise double dispatch does not work.

> 4. for every op, create a derived class of Visitor (e.g. Op1Visitor,
> Op2Visitor) e.g. and implement doOp() method.
>
> VISITOR SOLUTION analysis:
>
> Advantages:
> 1. For every new op, you have to add only one class with one virtual method
> 2. All logic pertaining to the new op is in one place (doOp method).
> Drawbacks:
> 1. There could be need in some dispatching logic in doOp() method
> 2. All doOp() methods may have to change if a new type is added
>
> EXAMPLE
>
> Enhance formatting of an XML document by adding a red border around the
> current depiction of only some elements, depending on the element type.
>
> CONCLUSION
>
> Consider using Visitor when the hierarchy of object types is stable and
> an op to add is not a natural extension of the type API that you would
> want to implement anyway.
>
> HTH
> -Pavel

Re: What is visitor pattern?

<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1091&group=comp.lang.c%2B%2B#1091

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!peer02.ams1!peer.ams1.xlned.com!news.xlned.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx17.iad.POSTED!not-for-mail
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad>
<6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
X-Mozilla-News-Host: news://ssl.astraweb.com
Message-ID: <9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 112
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Sun, 20 Aug 2023 22:02:03 UTC
Date: Sun, 20 Aug 2023 18:01:48 -0400
X-Received-Bytes: 5483
 by: Pavel - Sun, 20 Aug 2023 22:01 UTC

Öö Tiib wrote:
> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
>> wij wrote:
>>> I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
>>> but I still don't understand what it tries to say and the example code don't compile.
>>> Can anyone explain the visitor pattern or better webpages?
>>> probably making the example compile may help, thanks in advance.
>>>
>> This seems better than Wikipedia:
>>
>> https://www.gofpattern.com/behavioral/patterns/visitor-pattern.php
>>
>> Still I think both are slightly over-complicated / non-focused in how
>> they describe the original problem.
>>
>> I would describe it follows:
>>
>> PROBLEM
>>
>> 1. You have a collection or a stream of objects of different types thru
>> which you can iterate. Given [a ref to] any such object, you are able to
>> compute its type and/or call a virtual method.
>> 2. You want to iterate thru these objects and do some op1 with each of
>> them. Op1 depends on the object type (whole or part of this dependency
>> could be expressible by only calling virtual method(s) on a [ref to]
>> common base type).
>> 3. You will likely need to implement other similar operations, say, op2,
>> op3 etc
>>
>> OO SOLUTION
>>
>> 1. Ensure all objects have a common base class
>> 2. Add op1 (and later op2...) as a virtual method at the base class and
>> implement it in all most derived classes (or, if you are lucky, there
>> will be already some internal nodes in the hierarchy where you can plant
>> common logic for close siblings -- or you have to expand the hierarchy
>> to add such internal nodes)
>>
>> OO SOLUTION analysis
>>
>> Advantage: all dispatching is done for you by virtual method machinery
>> Drawback: need to change lots of classes every time you add one op, even
>> if you could implement op1,op2... using only public API of the object
>> type (maybe there are not many differences between how the op should
>> behave on the objects of all those many derived classes (but there are
>> some)).
>>
>> VISITOR SOLUTION
>>
>
> That is illustration of why I said "people's mind does not grasp double
> dispatch too well."
>
>> 1. Ensure all objects have a common base class (say, it's B)
>
> Not needed.
>
>> 2. create an abstract class Visitor with an abstract method doOp with an
>> arg of type [ref to] B.
>
> Nope, pile of overloads of doOp one for each type processed.
This would render the pattern useless as has no advantage over adding a
virtual method to do the op. The rationale of the pattern is to permit
coding one op in one place.

> Otherwise
> how you process different types differently?
I explained this in the problem statement. "Given [a ref to] any such
object, you are able to
compute its type and/or call a virtual method". In practice this can be
anything, examples (non-exhaustive): a enum type discriminator, virtual
cast method, (in modern languages), pattern matching.

>
>> 3. add a single method to B, e.g. acceptVisit that takes [ref to]
>> Visitor and calls doOp on it. NOTE: only one such method is needed, no
>> matter how many ops you are adding.
>
> Not enough. Every type processed has to have that copy-paste
> acceptVisit method. Otherwise double dispatch does not work.
Double dispatch works just fine without copy-pasting. Dispatch #1 (by
the operation type) is done by the virtual method doOp. Dispatch #2 (by
the object type) is done by using the actual type to call specific
methods and/or calling virtual methods, on the object ref.

>
>> 4. for every op, create a derived class of Visitor (e.g. Op1Visitor,
>> Op2Visitor) e.g. and implement doOp() method.
>>
>> VISITOR SOLUTION analysis:
>>
>> Advantages:
>> 1. For every new op, you have to add only one class with one virtual method
>> 2. All logic pertaining to the new op is in one place (doOp method).
>> Drawbacks:
>> 1. There could be need in some dispatching logic in doOp() method
>> 2. All doOp() methods may have to change if a new type is added
>>
>> EXAMPLE
>>
>> Enhance formatting of an XML document by adding a red border around the
>> current depiction of only some elements, depending on the element type.
>>
>> CONCLUSION
>>
>> Consider using Visitor when the hierarchy of object types is stable and
>> an op to add is not a natural extension of the type API that you would
>> want to implement anyway.
>>
>> HTH
>> -Pavel

Re: What is visitor pattern?

<ubu6un$1it4v$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1093&group=comp.lang.c%2B%2B#1093

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: alf.p.steinbach@gmail.com (Alf P. Steinbach)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Mon, 21 Aug 2023 01:17:42 +0200
Organization: A noiseless patient Spider
Lines: 179
Message-ID: <ubu6un$1it4v$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 20 Aug 2023 23:17:43 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="290106067b9983b28f7ad727d4af1299";
logging-data="1668255"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19YEIA+RL3CEqdO3gVUxrfH"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.14.0
Cancel-Lock: sha1:fI+bExs4TXlB9NN+RSXCTx0LZaA=
Content-Language: en-US
In-Reply-To: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
 by: Alf P. Steinbach - Sun, 20 Aug 2023 23:17 UTC

On 2023-08-20 3:55 PM, wij wrote:
> I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
> but I still don't understand what it tries to say and the example code don't compile.
> Can anyone explain the visitor pattern or better webpages?
> probably making the example compile may help, thanks in advance.

#include <fmt/core.h> // <url: https://github.com/fmtlib/fmt> tip:
define FMT_HEADER_ONLY

#include <variant>
#include <vector>

#include <math.h>

namespace cppm {
template< class Type > using in_ = const Type&;
} // namespace cppm

namespace geometry {
struct Point { double x; double y; };
struct Distance { double dx; double dy; };
struct Rect_size { double w; double h; };

constexpr auto operator+( const Point pt, const Distance d )
-> Point
{ return Point{ pt.x + d.dx, pt.y + d.dy }; }

constexpr auto operator-( const Point pt, const Distance d )
-> Point
{ return Point{ pt.x - d.dx, pt.y - d.dy }; }
} // namespace geometry

namespace math{
#ifndef M_PI
# error "Define `_USE_MATH_DEFINES` in the build to get Posix
constants like `M_PI`."
#endif
const double pi = M_PI;

template< class Number >
constexpr auto square_of( const Number x ) -> Number { return x*x; }
} // namespace math

namespace shape {
using geometry::Point, geometry::Distance, geometry::Rect_size;
using math::pi, math::square_of;

class Rectangle;

class Shape
{
Point m_lower_left;

protected:
Shape( const Point pt = {} ): m_lower_left( pt ) {}

public:
virtual ~Shape() {}

virtual auto area() const -> double = 0;

auto bb_pos() const -> Point { return
m_lower_left; }
virtual auto bb_size() const -> Rect_size = 0;
inline auto bounding_box() const -> Rectangle;
};

class Rectangle:
public Shape
{
Rect_size m_size;

public:
Rectangle(): Shape(), m_size() {}
Rectangle( const Point ll, const Rect_size size ): Shape( ll ),
m_size( size ) {}

auto area() const -> double { auto& _ = m_size; return
_.w*_.h; }
auto bb_size() const -> Rect_size override { return m_size; }
};

inline auto Shape::bounding_box() const -> Rectangle { return
Rectangle{ bb_pos(), bb_size() }; }

class Circle: public Shape
{
double m_radius;

public:
Circle(): Shape(), m_radius() {}

Circle( const Point center, double radius ):
Shape( center - Distance{ radius, radius } ),
m_radius( radius )
{}

auto radius() const -> double { return m_radius; }
auto diameter() const -> double { return 2*radius(); }
auto center() const -> Point { return bb_pos() +
Distance{ radius(), radius() }; }

auto area() const -> double { return pi*square_of(
m_radius ); }
auto bb_size() const -> Rect_size override { return
Rect_size{ diameter(), diameter() }; }
};

} // namespace shape

namespace scene {
using cppm::in_;
using shape::Shape, shape::Rectangle, shape::Circle;
using std::get, std::variant, std::visit, // <variant>
std::vector; // <vector>

class Shape_holder
{
Shape* m_p_shape;
variant<Rectangle, Circle> m_shape;

void set_pointer() { visit( [&]( auto& r ) { m_p_shape = &r; },
m_shape ); }

public:
template< class Concrete_shape >
Shape_holder( Concrete_shape shape ): m_shape( shape ) {
set_pointer(); }

Shape_holder( in_<Shape_holder> other ): m_shape( other.m_shape
) { set_pointer(); }

auto shape() -> Shape& { return *m_p_shape; }

template< class Visitor >
void pass_shape_to( Visitor&& visitor ) { visit( visitor,
m_shape ); }

template< class Visitor >
void pass_shape_to( Visitor&& visitor ) const { visit( visitor,
m_shape ); }
};

using Shapes = vector<Shape_holder>;
} // scene

auto main() -> int
{ using cppm::in_;
using geometry::Rect_size;
using scene::Shapes;
using shape::Rectangle, shape::Circle;

Shapes shapes = { Rectangle( {}, {1, 2} ), Circle( {}, 3 ) };
for( auto& holder: shapes ) {
struct Visitor
{
void operator()( in_<Rectangle> rect ) const
{
const Rect_size bb = rect.bb_size();
fmt::print( "Rectangle {}×{}.\n", bb.w, bb.h );
}

void operator()( in_<Circle> circle ) const
{
fmt::print( "Circle with radius {}.\n", circle.radius()
); // Only avail in Circle.
}
};

fmt::print( "Area {} in a ", holder.shape().area() ); //
Virtual call.
holder.pass_shape_to( Visitor() ); //
Visitation.
}
}

- Alf

Re: What is visitor pattern?

<ubu7as$1it63$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1094&group=comp.lang.c%2B%2B#1094

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: alf.p.steinbach@gmail.com (Alf P. Steinbach)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Mon, 21 Aug 2023 01:24:12 +0200
Organization: A noiseless patient Spider
Lines: 9
Message-ID: <ubu7as$1it63$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<ubu6un$1it4v$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 20 Aug 2023 23:24:13 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="290106067b9983b28f7ad727d4af1299";
logging-data="1668291"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+1rfBLoZvYDe0XarzZYQas"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.14.0
Cancel-Lock: sha1:ypHq7WPor86OMyOLN4JM6a7Exts=
Content-Language: en-US
In-Reply-To: <ubu6un$1it4v$1@dont-email.me>
 by: Alf P. Steinbach - Sun, 20 Aug 2023 23:24 UTC

On 2023-08-21 1:17 AM, Alf P. Steinbach wrote:
[snip code]

Some imprefections because I just wrote that and posted it. Then looked
at the posting and noticed should e.g. take care of assignment op. It's
the news-client's fault for providing a too easy to click "post" button.

- Alf

Re: What is visitor pattern?

<a374236f-a043-4521-b551-b489764a69f9n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1095&group=comp.lang.c%2B%2B#1095

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:620a:4709:b0:76d:8403:1aa4 with SMTP id bs9-20020a05620a470900b0076d84031aa4mr27150qkb.5.1692584655990;
Sun, 20 Aug 2023 19:24:15 -0700 (PDT)
X-Received: by 2002:a17:90b:d81:b0:26d:26eb:c577 with SMTP id
bg1-20020a17090b0d8100b0026d26ebc577mr1339117pjb.6.1692584655459; Sun, 20 Aug
2023 19:24:15 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Sun, 20 Aug 2023 19:24:14 -0700 (PDT)
In-Reply-To: <ea1ee058-e460-4e34-a001-4e9375f1a7can@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=124.218.76.41; posting-account=0Ek0TQoAAAAS0oceh95IuNV59QuIWNeN
NNTP-Posting-Host: 124.218.76.41
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com> <ea1ee058-e460-4e34-a001-4e9375f1a7can@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <a374236f-a043-4521-b551-b489764a69f9n@googlegroups.com>
Subject: Re: What is visitor pattern?
From: wyniijj5@gmail.com (wij)
Injection-Date: Mon, 21 Aug 2023 02:24:15 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 2452
 by: wij - Mon, 21 Aug 2023 02:24 UTC

On Sunday, August 20, 2023 at 10:22:48 PM UTC+8, Öö Tiib wrote:
> On Sunday, 20 August 2023 at 16:55:56 UTC+3, wij wrote:
> > I found a C++ example https://refactoring.guru/design-patterns/visitor/cpp/example
> > but I still don't understand what it tries to say and the example code don't compile.
> Racoon with buzzsaw indicates self-irony.
> Example that does not compile is smelly ... OTOH it perhaps just lacks #includes.
>
> #include <array>
> #include <iostream>
> #include <string>
> > Can anyone explain the visitor pattern or better webpages?
> Maybe wikipedia?
> <https://en.wikipedia.org/wiki/Visitor_pattern>
> > probably making the example compile may help, thanks in advance.
> Unsure ... people's mind does not grasp double dispatch too well.

Thank. When I saw "array" I habitually translate to "vector", so the 2nd
parameter in "std::array<const Component *, 2>" looked strange to me!!!
From the compiled example, it looked to me that 'Visitor pattern' simply means
a class family (Component) has a virtual member, say Accept(..) in the 'visitor'
case, whose definition is defined by another class member (e.g. Visit::xxx).... no more.

Re: What is visitor pattern?

<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1096&group=comp.lang.c%2B%2B#1096

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:ae9:f70e:0:b0:76c:81dc:afee with SMTP id s14-20020ae9f70e000000b0076c81dcafeemr26065qkg.12.1692591163194;
Sun, 20 Aug 2023 21:12:43 -0700 (PDT)
X-Received: by 2002:a17:90a:ce0a:b0:26b:b59:a115 with SMTP id
f10-20020a17090ace0a00b0026b0b59a115mr1026505pju.3.1692591162722; Sun, 20 Aug
2023 21:12:42 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Sun, 20 Aug 2023 21:12:41 -0700 (PDT)
In-Reply-To: <9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
Injection-Info: google-groups.googlegroups.com; posting-host=145.14.19.203; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 145.14.19.203
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Mon, 21 Aug 2023 04:12:43 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: Öö Tiib - Mon, 21 Aug 2023 04:12 UTC

On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
> Öö Tiib wrote:
> > On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
> >
> >> 1. Ensure all objects have a common base class (say, it's B)
> >
> > Not needed.
> >
> >> 2. create an abstract class Visitor with an abstract method doOp with an
> >> arg of type [ref to] B.
> >
> > Nope, pile of overloads of doOp one for each type processed.
>
> This would render the pattern useless as has no advantage over adding a
> virtual method to do the op. The rationale of the pattern is to permit
> coding one op in one place.
>
The Visitor class is that "one place"; doing same operation lets say printing
of 50 types in one function results with huge function that is headache
not advantage. Separate functions are testable and maintainable.

> > Otherwise
> > how you process different types differently?
> I explained this in the problem statement. "Given [a ref to] any such
> object, you are able to
> compute its type and/or call a virtual method".

IOW you do huge switch typeid ... case static_ cast or have the virtual
method (over what we were "gaining advantage") already there?
But we need no bloat from that pattern to do neither. These were the
things we wanted to get rid of.

> In practice this can be
> anything, examples (non-exhaustive): a enum type discriminator, virtual
> cast method, (in modern languages), pattern matching.
> >
> >> 3. add a single method to B, e.g. acceptVisit that takes [ref to]
> >> Visitor and calls doOp on it. NOTE: only one such method is needed, no
> >> matter how many ops you are adding.
> >
> > Not enough. Every type processed has to have that copy-paste
> > acceptVisit method. Otherwise double dispatch does not work.
>
> Double dispatch works just fine without copy-pasting. Dispatch #1 (by
> the operation type) is done by the virtual method doOp. Dispatch #2 (by
> the object type) is done by using the actual type to call specific
> methods and/or calling virtual methods, on the object ref.

Of course huge switch or calling virtual method (or now even multiple)
work without the whole pattern. Read up on "double dispatch".
It is tricky like I already said.

Re: What is visitor pattern?

<ubuoig$1ons4$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1097&group=comp.lang.c%2B%2B#1097

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bonita.Montero@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Mon, 21 Aug 2023 06:18:26 +0200
Organization: A noiseless patient Spider
Lines: 45
Message-ID: <ubuoig$1ons4$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 21 Aug 2023 04:18:24 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="bebcf752d5dd72ba4411673c0932c9fd";
logging-data="1859460"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1++l5TIUaQlktoz3iEw2w1RJpyEXIB/86s="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:tVBBQoVrokllLJ2Em52OpvZ6MZo=
In-Reply-To: <uIsEM.123835$QQFb.6082@fx38.iad>
Content-Language: de-DE
 by: Bonita Montero - Mon, 21 Aug 2023 04:18 UTC

You can better do this with functional programming. If you need
a performant solution you'd pass a function-object of a generic
type. If performance is not your concern or not necessary you'd
pass a function<>-object.
Take this example of a file-listing function for Win32:

void fileList( wchar_t const *path, function<bool ( WIN32_FIND_DATAW
const & )> const &fn, DWORD *pdwErr )
{ using namespace std;
if( pdwErr )
*pdwErr = NO_ERROR;
wstring fullPath = getAbsolutePath( path );
WIN32_FIND_DATAW fd;
HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
if( hFind == INVALID_HANDLE_VALUE )
{
if( GetLastError() == ERROR_FILE_NOT_FOUND )
return;
if( !pdwErr )
throw system_error( (int)GetLastError(), system_category(),
"FindFirstFileW() failed" );
*pdwErr = GetLastError();
return;
}
invoke_on_destruct closeFind(
[&]()
{
BOOL succ = FindClose( hFind );
assert(succ);
} );
wstring dir( extractDirectory( fullPath.c_str(), false ) );
do
if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp( fd.cFileName, L".." )
!= 0 && !fn( fd ) )
break;
while( FindNextFileW( hFind, &fd ) );
if( GetLastError() != ERROR_NO_MORE_FILES )
{
if( !pdwErr )
throw system_error( (int)GetLastError(), system_category(),
"FindNextFileW() failed" );
*pdwErr = GetLastError();
}
}

Re: What is visitor pattern?

<ubv1ke$1q0e7$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1098&group=comp.lang.c%2B%2B#1098

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Muttley@dastardlyhq.com
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Mon, 21 Aug 2023 06:53:02 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 18
Message-ID: <ubv1ke$1q0e7$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
Injection-Date: Mon, 21 Aug 2023 06:53:02 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="fda3c9894a8af2ff94db8756b8e459c1";
logging-data="1900999"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19zaxNyGoMaqOKTzUZz8t70"
Cancel-Lock: sha1:jcu5/BvDc5WkU5x1bDAhfte+e9k=
 by: Muttley@dastardlyhq.com - Mon, 21 Aug 2023 06:53 UTC

On Sun, 20 Aug 2023 21:12:41 -0700 (PDT)
=?UTF-8?B?w5bDtiBUaWli?= <ootiib@hot.ee> wrote:
>On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
>> object, you are able to
>> compute its type and/or call a virtual method".=20
>
>IOW you do huge switch typeid ... case static_ cast or have the virtual=20
>method (over what we were "gaining advantage") already there?
>But we need no bloat from that pattern to do neither. These were the
>things we wanted to get rid of.=20

IME most design patterns are algorithms any half decent programmer could
have thought up by themselves and/or have been around for half a century
already but they simply got repackaged for a new generation.

Old wine -> new bottle.

Re: What is visitor pattern?

<01a599fc-0731-45e8-80d2-6f8eb387821dn@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1099&group=comp.lang.c%2B%2B#1099

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:6214:18f1:b0:63f:7d73:dd4b with SMTP id ep17-20020a05621418f100b0063f7d73dd4bmr30423qvb.7.1692601841650;
Mon, 21 Aug 2023 00:10:41 -0700 (PDT)
X-Received: by 2002:a17:90a:c717:b0:26b:b78:c94f with SMTP id
o23-20020a17090ac71700b0026b0b78c94fmr1435915pjt.7.1692601841113; Mon, 21 Aug
2023 00:10:41 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Mon, 21 Aug 2023 00:10:40 -0700 (PDT)
In-Reply-To: <ubv1ke$1q0e7$1@dont-email.me>
Injection-Info: google-groups.googlegroups.com; posting-host=84.50.190.130; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 84.50.190.130
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com> <ubv1ke$1q0e7$1@dont-email.me>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <01a599fc-0731-45e8-80d2-6f8eb387821dn@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Mon, 21 Aug 2023 07:10:41 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 2628
 by: Öö Tiib - Mon, 21 Aug 2023 07:10 UTC

On Monday, 21 August 2023 at 09:53:20 UTC+3, Mut...@dastardlyhq.com wrote:
> On Sun, 20 Aug 2023 21:12:41 -0700 (PDT)
> =Öö Tiib <oot...@hot.ee> wrote:
> >On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
> >> object, you are able to
> >> compute its type and/or call a virtual method".
> >
> >IOW you do huge switch typeid ... case static_ cast or have the virtual
> >method (over what we were "gaining advantage") already there?
> >But we need no bloat from that pattern to do neither. These were the
> >things we wanted to get rid of.
>
> IME most design patterns are algorithms any half decent programmer could
> have thought up by themselves and/or have been around for half a century
> already but they simply got repackaged for a new generation.
>
> Old wine -> new bottle.
>
Double dispatch was first perhaps described by Dan Ingalls in seventies in
context of SmallTalk ... so you are correct that half a century old.
There seems to be no difference how to package, too lot of people do not
get the idea of it (but can be assigned to maintain) and result is either
broken product or the nuisance what it got rid of edited back in.

Re: What is visitor pattern?

<msVEM.440194$xMqa.182640@fx12.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1108&group=comp.lang.c%2B%2B#1108

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!news.neodome.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer02.ams4!peer.am4.highwinds-media.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx12.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad>
<6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 104
Message-ID: <msVEM.440194$xMqa.182640@fx12.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Tue, 22 Aug 2023 02:55:14 UTC
Date: Mon, 21 Aug 2023 22:55:07 -0400
X-Received-Bytes: 5252
 by: Pavel - Tue, 22 Aug 2023 02:55 UTC

Öö Tiib wrote:
> On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
>> Öö Tiib wrote:
>>> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
>>>
>>>> 1. Ensure all objects have a common base class (say, it's B)
>>>
>>> Not needed.
>>>
>>>> 2. create an abstract class Visitor with an abstract method doOp with an
>>>> arg of type [ref to] B.
>>>
>>> Nope, pile of overloads of doOp one for each type processed.
>>
>> This would render the pattern useless as has no advantage over adding a
>> virtual method to do the op. The rationale of the pattern is to permit
>> coding one op in one place.
>>
> The Visitor class is that "one place"; doing same operation lets say printing
> of 50 types in one function results with huge function that is headache
> not advantage. Separate functions are testable and maintainable.
>
>>> Otherwise
>>> how you process different types differently?
>> I explained this in the problem statement. "Given [a ref to] any such
>> object, you are able to
>> compute its type and/or call a virtual method".
>
> IOW you do huge switch typeid ... case static_ cast or have the virtual
> method (over what we were "gaining advantage") already there?
Even a switch with 30 cases is no worse than 30 methods although switch
is not always necessary (try to read the above instead of imagining).

The advantage is in having this logic in one place. If your visitor does
a coherent thing (which it is supposed to do; else why is it a single
visitor, there could be and usually would be common code for all or many
visited). The most pliant cases (that are exactly those gaining most
from applying a visitor pattern) may get by object virtual methods.
Simple example:

class BorderingVisitor: public AbstractVisitor {
public:
void doOp(const Shape& s) const override {
if (s.area() > 25) {
dc.drawRedRectangle(s.boundingRectangle().increaseBy(0.1));
}
}
private:
DrawingContext dc;
};

If we wanted a green border around a shape of any of 10 classes derived
from convex polygon (ConvexTriangle, ConvexQuadrilateral etc), red
border around a shape of any of 10 classes derived from Oval and no
border around any of 30 other zero-area shape classes, all we need to do
is to change doOp to:

void BorderingVisitor::doOp(const Shape& s) const {
if (s.area() > 25) {
const Rectangle br{s.boundingRectangle().increaseBy(0.1)};
if (const ConvexPolygon* cp = s.castToConvexPolygon()) {
dc.drawGreenRectangle(br);
}
else {
assert(!!s.castToOval());
dc.drawRedRectangle(br);
}
}
}

And this is the complete code for adding a new operation (virtual cast
is to be only defined once for all operations)

> But we need no bloat from that pattern to do neither. These were the
> things we wanted to get rid of.

Care to show us the code for your "non bloated" "one-place" visitor
class for the above 2 problems? (like I did, you can omit the code that
is common for all operations).

>
>> In practice this can be
>> anything, examples (non-exhaustive): a enum type discriminator, virtual
>> cast method, (in modern languages), pattern matching.
>>>
>>>> 3. add a single method to B, e.g. acceptVisit that takes [ref to]
>>>> Visitor and calls doOp on it. NOTE: only one such method is needed, no
>>>> matter how many ops you are adding.
>>>
>>> Not enough. Every type processed has to have that copy-paste
>>> acceptVisit method. Otherwise double dispatch does not work.
>>
>> Double dispatch works just fine without copy-pasting. Dispatch #1 (by
>> the operation type) is done by the virtual method doOp. Dispatch #2 (by
>> the object type) is done by using the actual type to call specific
>> methods and/or calling virtual methods, on the object ref.
>
> Of course huge switch or calling virtual method (or now even multiple)
> work without the whole pattern. Read up on "double dispatch".
> It is tricky like I already said.
>
Surely you are the most competent software engineer understanding
multiple dispatch. Care to point out a "huge switch" in either of the
above 2 examples?

Re: What is visitor pattern?

<AXVEM.568386$SuUf.28925@fx14.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1110&group=comp.lang.c%2B%2B#1110

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer02.ams4!peer.am4.highwinds-media.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx14.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <ubuoig$1ons4$1@dont-email.me>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 52
Message-ID: <AXVEM.568386$SuUf.28925@fx14.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Tue, 22 Aug 2023 03:28:32 UTC
Date: Mon, 21 Aug 2023 23:28:32 -0400
X-Received-Bytes: 2948
 by: Pavel - Tue, 22 Aug 2023 03:28 UTC

Bonita Montero wrote:
> You can better do this
I suspect we are talking about different "this"es. A design pattern is a
recipe for solving a problem of a defined class. What is the class of
problems that your code intends to demonstrate how to solve?

> with functional programming. If you need
> a  performant solution you'd pass a function-object of a generic
> type. If performance is not your concern or not necessary you'd
> pass a function<>-object.
> Take this example of a file-listing function for Win32:
>
> void fileList( wchar_t const *path, function<bool ( WIN32_FIND_DATAW
> const & )> const &fn, DWORD *pdwErr )
> {
>     using namespace std;
>     if( pdwErr )
>         *pdwErr = NO_ERROR;
>     wstring fullPath = getAbsolutePath( path );
>     WIN32_FIND_DATAW fd;
>     HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
>     if( hFind == INVALID_HANDLE_VALUE )
>     {
>         if( GetLastError() == ERROR_FILE_NOT_FOUND )
>             return;
>         if( !pdwErr )
>             throw system_error( (int)GetLastError(), system_category(),
> "FindFirstFileW() failed" );
>         *pdwErr = GetLastError();
>         return;
>     }
>     invoke_on_destruct closeFind(
>         [&]()
>         {
>             BOOL succ = FindClose( hFind );
>             assert(succ);
>         } );
>     wstring dir( extractDirectory( fullPath.c_str(), false ) );
>     do
>         if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp( fd.cFileName,
> L".." ) != 0 && !fn( fd ) )
>             break;
>     while( FindNextFileW( hFind, &fd ) );
>     if( GetLastError() != ERROR_NO_MORE_FILES )
>     {
>         if( !pdwErr )
>             throw system_error( (int)GetLastError(), system_category(),
> "FindNextFileW() failed" );
>         *pdwErr = GetLastError();
>     }
> }

Re: What is visitor pattern?

<uc1b4g$292ev$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1111&group=comp.lang.c%2B%2B#1111

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bonita.Montero@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Tue, 22 Aug 2023 05:47:30 +0200
Organization: A noiseless patient Spider
Lines: 56
Message-ID: <uc1b4g$292ev$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Tue, 22 Aug 2023 03:47:28 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="62bbf9da102e47dcc248bf7a87d7d8d8";
logging-data="2394591"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+mV9Rmq6JfBrbpkAFIgvcly95zIYRNJ9w="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:lHUcARZyCAfvJY/bpOPFVa6oz1I=
Content-Language: de-DE
In-Reply-To: <AXVEM.568386$SuUf.28925@fx14.iad>
 by: Bonita Montero - Tue, 22 Aug 2023 03:47 UTC

Am 22.08.2023 um 05:28 schrieb Pavel:
> Bonita Montero wrote:
>> You can better do this
> I suspect we are talking about different "this"es. A design pattern is
> a recipe for solving a problem of a defined class. What is the class of
> problems that your code intends to demonstrate how to solve?

Visitor pattern and inversion of control is basically the same.

>> with functional programming. If you need
>> a  performant solution you'd pass a function-object of a generic
>> type. If performance is not your concern or not necessary you'd
>> pass a function<>-object.
>> Take this example of a file-listing function for Win32:
>>
>> void fileList( wchar_t const *path, function<bool ( WIN32_FIND_DATAW
>> const & )> const &fn, DWORD *pdwErr )
>> {
>>      using namespace std;
>>      if( pdwErr )
>>          *pdwErr = NO_ERROR;
>>      wstring fullPath = getAbsolutePath( path );
>>      WIN32_FIND_DATAW fd;
>>      HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
>>      if( hFind == INVALID_HANDLE_VALUE )
>>      {
>>          if( GetLastError() == ERROR_FILE_NOT_FOUND )
>>              return;
>>          if( !pdwErr )
>>              throw system_error( (int)GetLastError(),
>> system_category(), "FindFirstFileW() failed" );
>>          *pdwErr = GetLastError();
>>          return;
>>      }
>>      invoke_on_destruct closeFind(
>>          [&]()
>>          {
>>              BOOL succ = FindClose( hFind );
>>              assert(succ);
>>          } );
>>      wstring dir( extractDirectory( fullPath.c_str(), false ) );
>>      do
>>          if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp(
>> fd.cFileName, L".." ) != 0 && !fn( fd ) )
>>              break;
>>      while( FindNextFileW( hFind, &fd ) );
>>      if( GetLastError() != ERROR_NO_MORE_FILES )
>>      {
>>          if( !pdwErr )
>>              throw system_error( (int)GetLastError(),
>> system_category(), "FindNextFileW() failed" );
>>          *pdwErr = GetLastError();
>>      }
>> }
>

Re: What is visitor pattern?

<LzWEM.65654$VPEa.6307@fx33.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1112&group=comp.lang.c%2B%2B#1112

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx33.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <uc1b4g$292ev$1@dont-email.me>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 62
Message-ID: <LzWEM.65654$VPEa.6307@fx33.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Tue, 22 Aug 2023 04:11:23 UTC
Date: Tue, 22 Aug 2023 00:11:23 -0400
X-Received-Bytes: 3409
 by: Pavel - Tue, 22 Aug 2023 04:11 UTC

Bonita Montero wrote:
> Am 22.08.2023 um 05:28 schrieb Pavel:
>> Bonita Montero wrote:
>>> You can better do this
>> I suspect we are talking about different "this"es. A design pattern is
>> a recipe for solving a problem of a defined class. What is the class
>> of problems that your code intends to demonstrate how to solve?
>
> Visitor pattern and inversion of control is basically the same.
What represents the abstract element and concrete elements of different
types derived from the abstract element -- all of which are the
mandatory participants of a Visitor problem -- in your code?

>
>>> with functional programming. If you need
>>> a  performant solution you'd pass a function-object of a generic
>>> type. If performance is not your concern or not necessary you'd
>>> pass a function<>-object.
>>> Take this example of a file-listing function for Win32:
>>>
>>> void fileList( wchar_t const *path, function<bool ( WIN32_FIND_DATAW
>>> const & )> const &fn, DWORD *pdwErr )
>>> {
>>>      using namespace std;
>>>      if( pdwErr )
>>>          *pdwErr = NO_ERROR;
>>>      wstring fullPath = getAbsolutePath( path );
>>>      WIN32_FIND_DATAW fd;
>>>      HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
>>>      if( hFind == INVALID_HANDLE_VALUE )
>>>      {
>>>          if( GetLastError() == ERROR_FILE_NOT_FOUND )
>>>              return;
>>>          if( !pdwErr )
>>>              throw system_error( (int)GetLastError(),
>>> system_category(), "FindFirstFileW() failed" );
>>>          *pdwErr = GetLastError();
>>>          return;
>>>      }
>>>      invoke_on_destruct closeFind(
>>>          [&]()
>>>          {
>>>              BOOL succ = FindClose( hFind );
>>>              assert(succ);
>>>          } );
>>>      wstring dir( extractDirectory( fullPath.c_str(), false ) );
>>>      do
>>>          if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp(
>>> fd.cFileName, L".." ) != 0 && !fn( fd ) )
>>>              break;
>>>      while( FindNextFileW( hFind, &fd ) );
>>>      if( GetLastError() != ERROR_NO_MORE_FILES )
>>>      {
>>>          if( !pdwErr )
>>>              throw system_error( (int)GetLastError(),
>>> system_category(), "FindNextFileW() failed" );
>>>          *pdwErr = GetLastError();
>>>      }
>>> }
>>
>

Re: What is visitor pattern?

<942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1113&group=comp.lang.c%2B%2B#1113

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:ac8:5987:0:b0:403:edaf:5952 with SMTP id e7-20020ac85987000000b00403edaf5952mr57551qte.1.1692680215104;
Mon, 21 Aug 2023 21:56:55 -0700 (PDT)
X-Received: by 2002:a05:6a00:b52:b0:68a:2c24:57ce with SMTP id
p18-20020a056a000b5200b0068a2c2457cemr4672193pfo.5.1692680214625; Mon, 21 Aug
2023 21:56:54 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Mon, 21 Aug 2023 21:56:53 -0700 (PDT)
In-Reply-To: <msVEM.440194$xMqa.182640@fx12.iad>
Injection-Info: google-groups.googlegroups.com; posting-host=145.14.19.203; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 145.14.19.203
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com> <msVEM.440194$xMqa.182640@fx12.iad>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Tue, 22 Aug 2023 04:56:55 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 7197
 by: Öö Tiib - Tue, 22 Aug 2023 04:56 UTC

On Tuesday, 22 August 2023 at 05:55:32 UTC+3, Pavel wrote:
> Öö Tiib wrote:
> > On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
> >> Öö Tiib wrote:
> >>> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
> >>>
> >>>> 1. Ensure all objects have a common base class (say, it's B)
> >>>
> >>> Not needed.
> >>>
> >>>> 2. create an abstract class Visitor with an abstract method doOp with an
> >>>> arg of type [ref to] B.
> >>>
> >>> Nope, pile of overloads of doOp one for each type processed.
> >>
> >> This would render the pattern useless as has no advantage over adding a
> >> virtual method to do the op. The rationale of the pattern is to permit
> >> coding one op in one place.
> >>
> > The Visitor class is that "one place"; doing same operation lets say printing
> > of 50 types in one function results with huge function that is headache
> > not advantage. Separate functions are testable and maintainable.
> >
> >>> Otherwise
> >>> how you process different types differently?
> >> I explained this in the problem statement. "Given [a ref to] any such
> >> object, you are able to
> >> compute its type and/or call a virtual method".
> >
> > IOW you do huge switch typeid ... case static_ cast or have the virtual
> > method (over what we were "gaining advantage") already there?
>
> Even a switch with 30 cases is no worse than 30 methods although switch
> is not always necessary (try to read the above instead of imagining).
>
Visitor is typically used to search, filter, draw or print whole data object
hierarchy, convert to JSON to XML or to tree in GUI. If whole data hierarchy
is small then you get 30 cases. Switch case is worse than virtual methods.
Think why virtual methods were added? To get rid of switch cases over type..
Visitor is not meant as excuse to add those back, otherwise just use
the switch case in function, do not manufacture visitors that do not use
double dispatch for confusion.

> The advantage is in having this logic in one place. If your visitor does
> a coherent thing (which it is supposed to do; else why is it a single
> visitor, there could be and usually would be common code for all or many
> visited). The most pliant cases (that are exactly those gaining most
> from applying a visitor pattern) may get by object virtual methods.
> Simple example:
>
> If we wanted a green border around a shape of any of 10 classes derived
> from convex polygon (ConvexTriangle, ConvexQuadrilateral etc), red
> border around a shape of any of 10 classes derived from Oval and no
> border around any of 30 other zero-area shape classes, all we need to do
> is to change doOp to:
>

Unused cp in your code?
Can't post sane code from gg ... but also don't want to install newsreaders
to all devices I use. It is drawing border to any shape and so it is unclear
why you need visitor. Logical one place is either DrwawingContext's or
Shape's nonvirtual method or free function:

void Shape::draw_border(DrawingContext &dc) const {
if (area() <= 25) return;
const Rectangle br{boundingRectangle().increaseBy(0.1)};
if (isConvexPolygon()) { dc.drawGreenRectangle(br); return; }
assert(isOval());
dc.drawRedRectangle(br);
}

>
> And this is the complete code for adding a new operation (virtual cast
> is to be only defined once for all operations)

You forget that you have BorderingVisitor class of unclear life , inject
DrawingContext to it (is it copy?), etc. result is

BorderingVisitor bv(dc);
s.acceptVisit(bv);
instead one of:

dc.draw_border(s);

s.draw_border(dc);

draw_border(dc, s);

> > But we need no bloat from that pattern to do neither. These were the
> > things we wanted to get rid of.
> Care to show us the code for your "non bloated" "one-place" visitor
> class for the above 2 problems? (like I did, you can omit the code that
> is common for all operations).

Yes, sorry for gg breaking all formating.
> >
> >> In practice this can be
> >> anything, examples (non-exhaustive): a enum type discriminator, virtual
> >> cast method, (in modern languages), pattern matching.
> >>>
> >>>> 3. add a single method to B, e.g. acceptVisit that takes [ref to]
> >>>> Visitor and calls doOp on it. NOTE: only one such method is needed, no
> >>>> matter how many ops you are adding.
> >>>
> >>> Not enough. Every type processed has to have that copy-paste
> >>> acceptVisit method. Otherwise double dispatch does not work.
> >>
> >> Double dispatch works just fine without copy-pasting. Dispatch #1 (by
> >> the operation type) is done by the virtual method doOp. Dispatch #2 (by
> >> the object type) is done by using the actual type to call specific
> >> methods and/or calling virtual methods, on the object ref.
> >
> > Of course huge switch or calling virtual method (or now even multiple)
> > work without the whole pattern. Read up on "double dispatch".
> > It is tricky like I already said.
> >
> Surely you are the most competent software engineer understanding
> multiple dispatch. Care to point out a "huge switch" in either of the
> above 2 examples?

There are no double dispatch in your code so the whole acceptVisit, doOp
add nothing. These were entirely added to do double dispatch to add
virtual methods to large potentially unrelated data hierarchies without
changing any of classes in those hierarchies. What you do is not even
use case for visitor pattern.

Re: What is visitor pattern?

<uc29p5$2dgb7$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1122&group=comp.lang.c%2B%2B#1122

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bonita.Montero@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Tue, 22 Aug 2023 14:30:31 +0200
Organization: A noiseless patient Spider
Lines: 69
Message-ID: <uc29p5$2dgb7$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
<LzWEM.65654$VPEa.6307@fx33.iad>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Tue, 22 Aug 2023 12:30:29 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="62bbf9da102e47dcc248bf7a87d7d8d8";
logging-data="2539879"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/T16U+AVM6utf0CR7ShyYMx/zqOCK7weQ="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:kVq4hkwc1JiyECye49ngClogEes=
In-Reply-To: <LzWEM.65654$VPEa.6307@fx33.iad>
Content-Language: de-DE
 by: Bonita Montero - Tue, 22 Aug 2023 12:30 UTC

Am 22.08.2023 um 06:11 schrieb Pavel:
> Bonita Montero wrote:
>> Am 22.08.2023 um 05:28 schrieb Pavel:
>>> Bonita Montero wrote:
>>>> You can better do this
>>> I suspect we are talking about different "this"es. A design pattern is
>>> a recipe for solving a problem of a defined class. What is the class
>>> of problems that your code intends to demonstrate how to solve?
>>
>> Visitor pattern and inversion of control is basically the same.
> What represents the abstract element and concrete elements of different
> types derived from the abstract element -- all of which are the
> mandatory participants of a Visitor problem -- in your code?

My code and the visitor-pattern have in common that
there's some callback with its own state, i.e. both
have some inversion of control

>>
>>>> with functional programming. If you need
>>>> a  performant solution you'd pass a function-object of a generic
>>>> type. If performance is not your concern or not necessary you'd
>>>> pass a function<>-object.
>>>> Take this example of a file-listing function for Win32:
>>>>
>>>> void fileList( wchar_t const *path, function<bool ( WIN32_FIND_DATAW
>>>> const & )> const &fn, DWORD *pdwErr )
>>>> {
>>>>      using namespace std;
>>>>      if( pdwErr )
>>>>          *pdwErr = NO_ERROR;
>>>>      wstring fullPath = getAbsolutePath( path );
>>>>      WIN32_FIND_DATAW fd;
>>>>      HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
>>>>      if( hFind == INVALID_HANDLE_VALUE )
>>>>      {
>>>>          if( GetLastError() == ERROR_FILE_NOT_FOUND )
>>>>              return;
>>>>          if( !pdwErr )
>>>>              throw system_error( (int)GetLastError(),
>>>> system_category(), "FindFirstFileW() failed" );
>>>>          *pdwErr = GetLastError();
>>>>          return;
>>>>      }
>>>>      invoke_on_destruct closeFind(
>>>>          [&]()
>>>>          {
>>>>              BOOL succ = FindClose( hFind );
>>>>              assert(succ);
>>>>          } );
>>>>      wstring dir( extractDirectory( fullPath.c_str(), false ) );
>>>>      do
>>>>          if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp(
>>>> fd.cFileName, L".." ) != 0 && !fn( fd ) )
>>>>              break;
>>>>      while( FindNextFileW( hFind, &fd ) );
>>>>      if( GetLastError() != ERROR_NO_MORE_FILES )
>>>>      {
>>>>          if( !pdwErr )
>>>>              throw system_error( (int)GetLastError(),
>>>> system_category(), "FindNextFileW() failed" );
>>>>          *pdwErr = GetLastError();
>>>>      }
>>>> }
>>>
>>
>

Re: What is visitor pattern?

<G1CFM.897823$GMN3.400773@fx16.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1163&group=comp.lang.c%2B%2B#1163

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx16.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad>
<6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
<msVEM.440194$xMqa.182640@fx12.iad>
<942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 301
Message-ID: <G1CFM.897823$GMN3.400773@fx16.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Thu, 24 Aug 2023 05:38:46 UTC
Date: Thu, 24 Aug 2023 01:38:27 -0400
X-Received-Bytes: 15809
 by: Pavel - Thu, 24 Aug 2023 05:38 UTC

Öö Tiib wrote:
> On Tuesday, 22 August 2023 at 05:55:32 UTC+3, Pavel wrote:
>> Öö Tiib wrote:
>>> On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
>>>> Öö Tiib wrote:
>>>>> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
>>>>>
>>>>>> 1. Ensure all objects have a common base class (say, it's B)
>>>>>
>>>>> Not needed.
>>>>>
>>>>>> 2. create an abstract class Visitor with an abstract method doOp with an
>>>>>> arg of type [ref to] B.
>>>>>
>>>>> Nope, pile of overloads of doOp one for each type processed.
>>>>
>>>> This would render the pattern useless as has no advantage over adding a
>>>> virtual method to do the op. The rationale of the pattern is to permit
>>>> coding one op in one place.
>>>>
>>> The Visitor class is that "one place"; doing same operation lets say printing
>>> of 50 types in one function results with huge function that is headache
>>> not advantage. Separate functions are testable and maintainable.
>>>
>>>>> Otherwise
>>>>> how you process different types differently?
>>>> I explained this in the problem statement. "Given [a ref to] any such
>>>> object, you are able to
>>>> compute its type and/or call a virtual method".
>>>
>>> IOW you do huge switch typeid ... case static_ cast or have the virtual
>>> method (over what we were "gaining advantage") already there?
>>
>> Even a switch with 30 cases is no worse than 30 methods although switch
>> is not always necessary (try to read the above instead of imagining).
>>
> Visitor is typically used to search, filter, draw or print whole data object
> hierarchy, convert to JSON to XML or to tree in GUI.
correct

> If whole data hierarchy
> is small then you get 30 cases. Switch case is worse than virtual methods.
*In general* neither is better or worse. In particular, as I explained
at the beginning, if the operation is decomposed correctly, its behavior
on the objects of different types has to be coherent, similar in some
way (and maybe more similar than different) and, as such, a significant
parts of the context or results of intermediate computations could be
shared. I demonstrated this in my example with red and green borders: a)
a condition by area prevents visitor from operating on objects is
computed from their property that is orthogonal to their dynamic type;
and b) the exact behavior of the operation (red vs green border in the
example) depends on a subset of types (which, in general, is not
necessarily compact in the hierarchy).

> Think why virtual methods were added? To get rid of switch cases over type.
Of course, not. Virtual methods were *used*, with less or greater
success, to replace switch statements in event-processing scenarios
(like window behavior) (with greater success) or in state machines (with
lesser success).

But, they were *invented* to implement polymorphic behavior and
relatively loose coupling (generally, lesser dependencies) between the
code that calls the method and the code that implements the method.

Obviously, a single switch statement couples everything together and the
compilation unit where the switch is depends on every piece of code and
every concrete type the switch statement handles -- to the extent its
behavior in the operation must differ from that of other types). But
this loose coupling is only desirable when the behaviors are severely
different. On the other hand, when the operation does *to significant
extent, a single thing* on different type, with 2-3 relatively small
type-dependent differences, these differences are often better expressed
in if statement, switch or in a number of different ways (including
calling combinations of virtual functions *from within the top-level
method implementing the operation*)

> Visitor is not meant as excuse to add those back, otherwise just use
> the switch case in function, do not manufacture visitors that do not use
> double dispatch for confusion.
Ohh. Not again. If you want to use virtual functions, use them, you
don't need visitor for this. Add virtual void newOperation(context
parameters) to the base class and call it in some for_each. This is
exactly what I explained in the first post: Visitor itself is an
alternative to adding a virtual methods. The criteria which one to
choose are well known from the original works on Visitor, like GoF etc:
if your type hierarchy is big, stable, its model is well understood and
established (like GUI toolkit), and hence you are unlikely to change the
hierarchy often BUT you need to add new operations often, use visitors
(because you don't need to add thing to every class for every
operation). If your type hierarchy is dynamic and is expected to grow
often but the set of operation is stable, well establish, unlikely to
change often (like unit actions in a strategy game where you add and
enhance units but all they are going to do is to essentially move, shoot
and die), add a virtual method.

The first thing to explain about Visitor (or any other design pattern)
is how to decide when to use it and when not to use it (the scope).

If the decision to use Visitor is correct, we already know the class
hierarchy is stable and there is no harm for the code to depend on a
fixed set of these classes. The double dispatch for Visitor is just a
tool to dispatch to the code specific to the type after you dispatched
to the specific operation. Nothing more, nothing less, see definition of
multiple dispatch. The specific way to double-dispatch that many Visitor
examples (unfortunately, started with GoF book, and shown in Wikipedia)
show, is simply the *implementation detail*. You do not have to trust me.

Says Wikipedia:

"In software engineering, double dispatch is a special form of multiple
dispatch, and a mechanism that dispatches a function call to different
concrete functions depending on the runtime types of two objects
involved in the call"

And, looking at same Wikipedia on multiple dispatch, C++ is *not* one of
the languages that natively support multiple dispatch and there are
multiple ways of implementing it, among them
- "using run time type comparison via dynamic_cast" (if statement method)
- "pointer-to-method lookup table"; and (misleadingly)
- "the visitor pattern"

Why "misleadingly"? Because, looking at visitor pattern, you find

"The visitor takes the instance reference as input, and implements the
goal through double dispatch."

So, according to Wikipedia article on multiple dispatch one can
implement it (among the others) using visitor pattern, whereas visitor
pattern "implements the goal via double dispatch" whereas the double
dispatch is a special form of multiple dispatch.

Some readers (which seem to include you) resolve this circular reference
ad-hoc: they see that *specific implementation* of multiple dispatch in
C++ that happens to illustrate the Visitor article (stemming from the
GoF book, unfortunately) and somehow decide that this is *the right way*
(TM) to implement double dispatch. This is despite:

- that double dispatch is defined as a concept an there is no *the right
way* of doing it in C++ and Wikipedia itself illustrates two such ways
(both different from the one used in the visitor article and GoF book)
in the article on multiple dispatch.

- that it must be obvious that it is Visitor that uses double dispatch
in its implementation, not other may around, because the part cannot use
the whole and Visitor is "bigger" than double-dispatch because it uses
both double dispatch and iteration (through the objects in a data
structure) but iteration is not a part of double dispatch.

The problem with that (by and large, randomly-selected) implementation
of double dispatch is that it is a bad choice to illustrate Visitor
pattern specifically. Besides the mere distracting the reader to its
clever *implementation details* (not essential for understanding the
Visitor pattern), it also makes it difficult to emphasize the coherence
and cohesiveness of the newly added operation and does nothing to
explain how to organize the access of the new operation to all pieces of
data it may need. Taking into account that the whole Visitor pattern is
about adding a new operation to working on a collection or stream ("the
structure") of objects, it is a very unfortunate choice indeed.

>
>> The advantage is in having this logic in one place. If your visitor does
>> a coherent thing (which it is supposed to do; else why is it a single
>> visitor, there could be and usually would be common code for all or many
>> visited). The most pliant cases (that are exactly those gaining most
>> from applying a visitor pattern) may get by object virtual methods.
>> Simple example:
>>
>> If we wanted a green border around a shape of any of 10 classes derived
>> from convex polygon (ConvexTriangle, ConvexQuadrilateral etc), red
>> border around a shape of any of 10 classes derived from Oval and no
>> border around any of 30 other zero-area shape classes, all we need to do
>> is to change doOp to:
>>
>
> Unused cp in your code?
Yes, I started with taking bounding rectangle from every type separately
(which sometimes may be a valid micro-optimization if we use a fully
qualified non-virtual call; but then decided to keep it simple to
emphasize the points I wanted to emphasize)


Click here to read the complete article
Re: What is visitor pattern?

<niCFM.897824$GMN3.379171@fx16.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1164&group=comp.lang.c%2B%2B#1164

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx16.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
<LzWEM.65654$VPEa.6307@fx33.iad> <uc29p5$2dgb7$1@dont-email.me>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <uc29p5$2dgb7$1@dont-email.me>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 82
Message-ID: <niCFM.897824$GMN3.379171@fx16.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Thu, 24 Aug 2023 05:56:35 UTC
Date: Thu, 24 Aug 2023 01:56:35 -0400
X-Received-Bytes: 4502
 by: Pavel - Thu, 24 Aug 2023 05:56 UTC

Bonita Montero wrote:
> Am 22.08.2023 um 06:11 schrieb Pavel:
>> Bonita Montero wrote:
>>> Am 22.08.2023 um 05:28 schrieb Pavel:
>>>> Bonita Montero wrote:
>>>>> You can better do this
>>>> I suspect we are talking about different "this"es. A design pattern is
>>>> a recipe for solving a problem of a defined class. What is the class
>>>> of problems that your code intends to demonstrate how to solve?
>>>
>>> Visitor pattern and inversion of control is basically the same.
>> What represents the abstract element and concrete elements of
>> different types derived from the abstract element -- all of which are
>> the mandatory participants of a Visitor problem -- in your code?
>
> My code and the visitor-pattern have in common that
> there's some callback with its own state, i.e. both
> have some inversion of control
IoC is very generic so a Visitor-pattern *framework* library can likely
be characterized as IoC; but then in your code the "template method" of
the framework (fileList) does not work on an object of type from some
non-trivial type hierarchy which is where the Visitor can be applied. Of
course you can argue that the type WIN32_FIND_DATAW represents a
degenerative hierarchy of one type but Visitor is not useful for working
on degenerative hierarchies. Your code is some custom framework to
iterate thru files; could be even useful but one cannot "do better" in
solving a problem by given class by solving some random problem of
entirely different class.

>
>
>>>
>>>>> with functional programming. If you need
>>>>> a  performant solution you'd pass a function-object of a generic
>>>>> type. If performance is not your concern or not necessary you'd
>>>>> pass a function<>-object.
>>>>> Take this example of a file-listing function for Win32:
>>>>>
>>>>> void fileList( wchar_t const *path, function<bool (
>>>>> WIN32_FIND_DATAW const & )> const &fn, DWORD *pdwErr )
>>>>> {
>>>>>      using namespace std;
>>>>>      if( pdwErr )
>>>>>          *pdwErr = NO_ERROR;
>>>>>      wstring fullPath = getAbsolutePath( path );
>>>>>      WIN32_FIND_DATAW fd;
>>>>>      HANDLE hFind = FindFirstFileW( fullPath.c_str(), &fd );
>>>>>      if( hFind == INVALID_HANDLE_VALUE )
>>>>>      {
>>>>>          if( GetLastError() == ERROR_FILE_NOT_FOUND )
>>>>>              return;
>>>>>          if( !pdwErr )
>>>>>              throw system_error( (int)GetLastError(),
>>>>> system_category(), "FindFirstFileW() failed" );
>>>>>          *pdwErr = GetLastError();
>>>>>          return;
>>>>>      }
>>>>>      invoke_on_destruct closeFind(
>>>>>          [&]()
>>>>>          {
>>>>>              BOOL succ = FindClose( hFind );
>>>>>              assert(succ);
>>>>>          } );
>>>>>      wstring dir( extractDirectory( fullPath.c_str(), false ) );
>>>>>      do
>>>>>          if( wcscmp( fd.cFileName, L"." ) != 0 && wcscmp(
>>>>> fd.cFileName, L".." ) != 0 && !fn( fd ) )
>>>>>              break;
>>>>>      while( FindNextFileW( hFind, &fd ) );
>>>>>      if( GetLastError() != ERROR_NO_MORE_FILES )
>>>>>      {
>>>>>          if( !pdwErr )
>>>>>              throw system_error( (int)GetLastError(),
>>>>> system_category(), "FindNextFileW() failed" );
>>>>>          *pdwErr = GetLastError();
>>>>>      }
>>>>> }
>>>>
>>>
>>
>

Re: What is visitor pattern?

<uc703b$3cer6$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1165&group=comp.lang.c%2B%2B#1165

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bonita.Montero@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Thu, 24 Aug 2023 09:15:57 +0200
Organization: A noiseless patient Spider
Lines: 17
Message-ID: <uc703b$3cer6$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
<LzWEM.65654$VPEa.6307@fx33.iad> <uc29p5$2dgb7$1@dont-email.me>
<niCFM.897824$GMN3.379171@fx16.iad>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 24 Aug 2023 07:15:55 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="b01a33b29d39c87f910657740dee042d";
logging-data="3554150"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18/dmXRjcuUNgR+X5lBljsjMKNNgxWak3s="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:HosQdCVRkpn/Sk8YonrXql7kcc4=
In-Reply-To: <niCFM.897824$GMN3.379171@fx16.iad>
Content-Language: de-DE
 by: Bonita Montero - Thu, 24 Aug 2023 07:15 UTC

Am 24.08.2023 um 07:56 schrieb Pavel:

> IoC is very generic so a Visitor-pattern *framework* library can likely
> be characterized as IoC; but then in your code the "template method" of
> the framework (fileList) does not work on an object of type from some
> non-trivial type hierarchy which is where the Visitor can be applied.
> Of course you can argue that the type WIN32_FIND_DATAW represents a
> degenerative hierarchy of one type but Visitor is not useful for
> working on degenerative hierarchies. Your code is some custom
> framework to iterate thru files; could be even useful but one
> cannot "do better" in solving a problem by given class by solving
> some random problem of entirely different class.

The visitor pattern is a IoC-pattern, but not every IoC-pattern is a
visitor pattern. I like functional programming and I think that the
visitor pattern can be enhanced in this way, making it more IoC-ish.

Re: What is visitor pattern?

<a0da9e2a-a015-4497-96bc-8f9fbff3957an@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1166&group=comp.lang.c%2B%2B#1166

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:ad4:55d0:0:b0:649:463d:bf40 with SMTP id bt16-20020ad455d0000000b00649463dbf40mr240983qvb.1.1692877515849;
Thu, 24 Aug 2023 04:45:15 -0700 (PDT)
X-Received: by 2002:a17:90b:388:b0:269:6494:cbc8 with SMTP id
ga8-20020a17090b038800b002696494cbc8mr3958656pjb.4.1692877515579; Thu, 24 Aug
2023 04:45:15 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!1.us.feeder.erje.net!feeder.erje.net!border-1.nntp.ord.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Thu, 24 Aug 2023 04:45:14 -0700 (PDT)
In-Reply-To: <G1CFM.897823$GMN3.400773@fx16.iad>
Injection-Info: google-groups.googlegroups.com; posting-host=84.50.190.130; posting-account=pysjKgkAAACLegAdYDFznkqjgx_7vlUK
NNTP-Posting-Host: 84.50.190.130
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com> <msVEM.440194$xMqa.182640@fx12.iad>
<942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com> <G1CFM.897823$GMN3.400773@fx16.iad>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <a0da9e2a-a015-4497-96bc-8f9fbff3957an@googlegroups.com>
Subject: Re: What is visitor pattern?
From: ootiib@hot.ee (Öö Tiib)
Injection-Date: Thu, 24 Aug 2023 11:45:15 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Lines: 464
 by: Öö Tiib - Thu, 24 Aug 2023 11:45 UTC

On Thursday, 24 August 2023 at 08:39:04 UTC+3, Pavel wrote:
> Öö Tiib wrote:
> > On Tuesday, 22 August 2023 at 05:55:32 UTC+3, Pavel wrote:
> >> Öö Tiib wrote:
> >>> On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
> >>>> Öö Tiib wrote:
> >>>>> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
> >>>>>
> >>>>>> 1. Ensure all objects have a common base class (say, it's B)
> >>>>>
> >>>>> Not needed.
> >>>>>
> >>>>>> 2. create an abstract class Visitor with an abstract method doOp with an
> >>>>>> arg of type [ref to] B.
> >>>>>
> >>>>> Nope, pile of overloads of doOp one for each type processed.
> >>>>
> >>>> This would render the pattern useless as has no advantage over adding a
> >>>> virtual method to do the op. The rationale of the pattern is to permit
> >>>> coding one op in one place.
> >>>>
> >>> The Visitor class is that "one place"; doing same operation lets say printing
> >>> of 50 types in one function results with huge function that is headache
> >>> not advantage. Separate functions are testable and maintainable.
> >>>
> >>>>> Otherwise
> >>>>> how you process different types differently?
> >>>> I explained this in the problem statement. "Given [a ref to] any such
> >>>> object, you are able to
> >>>> compute its type and/or call a virtual method".
> >>>
> >>> IOW you do huge switch typeid ... case static_ cast or have the virtual
> >>> method (over what we were "gaining advantage") already there?
> >>
> >> Even a switch with 30 cases is no worse than 30 methods although switch
> >> is not always necessary (try to read the above instead of imagining).
> >>
> > Visitor is typically used to search, filter, draw or print whole data object
> > hierarchy, convert to JSON to XML or to tree in GUI.
> correct
> > If whole data hierarchy
> > is small then you get 30 cases. Switch case is worse than virtual methods.
>
> *In general* neither is better or worse.

Switch case over type is in general worse than virtual functions. Longer
function, bigger cyclomatic complexity, harder to understand, harder to
form confidence that it is valid, harder to maintain, harder to test and
also may need more access to implementation details of all types
involved, breaking encapsulation.

> In particular, as I explained
> at the beginning, if the operation is decomposed correctly, its behavior
> on the objects of different types has to be coherent, similar in some
> way (and maybe more similar than different) and, as such, a significant
> parts of the context or results of intermediate computations could be
> shared.

Translating data hierarchy to xml for particular version of particular
protocol while supporting several such in parallel? There can be
intermediate computations shared but all are typically in in visitor
classes or helpers of those. No one wants the classes in hierarchy
to know anything about xml whatsoever, nothing to talk about
particular brand used in particular version of kinds of end-points.

> I demonstrated this in my example with red and green borders: a)
> a condition by area prevents visitor from operating on objects is
> computed from their property that is orthogonal to their dynamic type;
> and b) the exact behavior of the operation (red vs green border in the
> example) depends on a subset of types (which, in general, is not
> necessarily compact in the hierarchy).
>
Your example did not need visitor pattern.

> > Think why virtual methods were added? To get rid of switch cases over type.
> Of course, not. Virtual methods were *used*, with less or greater
> success, to replace switch statements in event-processing scenarios
> (like window behavior) (with greater success) or in state machines (with
> lesser success).
>
> But, they were *invented* to implement polymorphic behavior and
> relatively loose coupling (generally, lesser dependencies) between the
> code that calls the method and the code that implements the method.
>
Same loose coupling is with code that calls function that does switch
case over type, so that kind of victory wasn't achieved.

> Obviously, a single switch statement couples everything together and the
> compilation unit where the switch is depends on every piece of code and
> every concrete type the switch statement handles -- to the extent its
> behavior in the operation must differ from that of other types). But
> this loose coupling is only desirable when the behaviors are severely
> different.
>
I don't follow what you are saying. Different stock markets and other
financial institutions for example are not severely different in essence,
but the format of data you are expected to exchange with their servers
differs massively enough.

> On the other hand, when the operation does *to significant
> extent, a single thing* on different type, with 2-3 relatively small
> type-dependent differences, these differences are often better expressed
> in if statement, switch or in a number of different ways (including
> calling combinations of virtual functions *from within the top-level
> method implementing the operation*)
>
That is not use-case of visitor pattern.

> > Visitor is not meant as excuse to add those back, otherwise just use
> > the switch case in function, do not manufacture visitors that do not use
> > double dispatch for confusion.
>
> Ohh. Not again. If you want to use virtual functions, use them, you
> don't need visitor for this. Add virtual void newOperation(context
> parameters) to the base class and call it in some for_each. This is
> exactly what I explained in the first post: Visitor itself is an
> alternative to adding a virtual methods.
>
You add same number of virtual methods of visitor if you need several
different classes of visitors to visit over same data hierarchies. The
gain is that these are in one place, in particular visitor and that the
classes in hierarchies are not changed by single letter.

> The criteria which one to
> choose are well known from the original works on Visitor, like GoF etc:
> if your type hierarchy is big, stable, its model is well understood and
> established (like GUI toolkit), and hence you are unlikely to change the
> hierarchy often BUT you need to add new operations often, use visitors
> (because you don't need to add thing to every class for every
> operation). If your type hierarchy is dynamic and is expected to grow
> often but the set of operation is stable, well establish, unlikely to
> change often (like unit actions in a strategy game where you add and
> enhance units but all they are going to do is to essentially move, shoot
> and die), add a virtual method.
>
> The first thing to explain about Visitor (or any other design pattern)
> is how to decide when to use it and when not to use it (the scope).
>
That is true, but you seem to suggest to misuse it, where unneeded.

> If the decision to use Visitor is correct, we already know the class
> hierarchy is stable and there is no harm for the code to depend on a
> fixed set of these classes. The double dispatch for Visitor is just a
> tool to dispatch to the code specific to the type after you dispatched
> to the specific operation. Nothing more, nothing less, see definition of
> multiple dispatch. The specific way to double-dispatch that many Visitor
> examples (unfortunately, started with GoF book, and shown in Wikipedia)
> show, is simply the *implementation detail*. You do not have to trust me.
>
Do not touch multiple dispatch yet. Going there now is like going into
four dimensional math when you haven't yet got the planar 2D grid
to work. Stay firmly within studying double dispatch until you understand
what it is.

> Says Wikipedia:
>
> "In software engineering, double dispatch is a special form of multiple
> dispatch, and a mechanism that dispatches a function call to different
> concrete functions depending on the runtime types of two objects
> involved in the call"
>
> And, looking at same Wikipedia on multiple dispatch, C++ is *not* one of
> the languages that natively support multiple dispatch and there are
> multiple ways of implementing it, among them
> - "using run time type comparison via dynamic_cast" (if statement method)
> - "pointer-to-method lookup table"; and (misleadingly)
> - "the visitor pattern"
>
> Why "misleadingly"? Because, looking at visitor pattern, you find
>
> "The visitor takes the instance reference as input, and implements the
> goal through double dispatch."
>
> So, according to Wikipedia article on multiple dispatch one can
> implement it (among the others) using visitor pattern, whereas visitor
> pattern "implements the goal via double dispatch" whereas the double
> dispatch is a special form of multiple dispatch.
>
Yes. you were confused by first sentence in wikipedia and stopped to
read there. Double dispatch is multiple dispatch like 2D grid is special
case of 4 dimensional room with 2 dimensions being of zero size.


Click here to read the complete article
Re: What is visitor pattern?

<gcSFM.312013$Fgta.22420@fx10.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1180&group=comp.lang.c%2B%2B#1180

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx10.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
<LzWEM.65654$VPEa.6307@fx33.iad> <uc29p5$2dgb7$1@dont-email.me>
<niCFM.897824$GMN3.379171@fx16.iad> <uc703b$3cer6$1@dont-email.me>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <uc703b$3cer6$1@dont-email.me>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 30
Message-ID: <gcSFM.312013$Fgta.22420@fx10.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Fri, 25 Aug 2023 00:02:20 UTC
Date: Thu, 24 Aug 2023 20:02:11 -0400
X-Received-Bytes: 2545
 by: Pavel - Fri, 25 Aug 2023 00:02 UTC

Bonita Montero wrote:
> Am 24.08.2023 um 07:56 schrieb Pavel:
>
>> IoC is very generic so a Visitor-pattern *framework* library can
>> likely be characterized as IoC; but then in your code the "template
>> method" of the framework (fileList) does not work on an object of type
>> from some non-trivial type hierarchy which is where the Visitor can be
>> applied.
>> Of  course you can argue that the type WIN32_FIND_DATAW represents a
>> degenerative hierarchy of one type but Visitor is not useful for
>> working  on degenerative hierarchies. Your code is some custom
>> framework to  iterate thru files; could be even useful but one
>> cannot "do better" in solving a problem by given class by solving
>> some random problem of entirely different class.
>
> The visitor pattern is a IoC-pattern, but not every IoC-pattern is a
> visitor pattern. I like functional programming and I think that the
> visitor pattern can be enhanced in this way, making it more IoC-ish.
>
You threw an interesting tangential idea (that IoC-ness is a numerical
property of a pattern) that I am willing to explore but let's put the
main issue to bed first:

Are you saying that, for whatever cause (like making Visitor more
IoC-ish) you are willing to drastically narrow the class of problems
that the pattern commonly-known as Visitor is believed to solve?

Specifically, can there exist an IoC framework that you would be ready
to characterize as correctly implementing Visitor pattern if that
framework could visit elements of only one type?

Re: What is visitor pattern?

<XZUFM.137111$PlBb.67508@fx42.iad>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1181&group=comp.lang.c%2B%2B#1181

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx42.iad.POSTED!not-for-mail
Subject: Re: What is visitor pattern?
Newsgroups: comp.lang.c++
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad>
<6df46174-6867-4577-a73d-0fb70d6a25e8n@googlegroups.com>
<9ea1f202-4524-03b8-f003-e11b7fa411e7@removeyourself.dontspam.yahoo>
<c772c32e-d0e0-4199-b173-c64e3535159cn@googlegroups.com>
<msVEM.440194$xMqa.182640@fx12.iad>
<942afb61-7d90-4251-87a3-18cf4c68fa03n@googlegroups.com>
<G1CFM.897823$GMN3.400773@fx16.iad>
<a0da9e2a-a015-4497-96bc-8f9fbff3957an@googlegroups.com>
From: pauldontspamtolk@removeyourself.dontspam.yahoo (Pavel)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0 SeaMonkey/2.53.17
MIME-Version: 1.0
In-Reply-To: <a0da9e2a-a015-4497-96bc-8f9fbff3957an@googlegroups.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Lines: 580
Message-ID: <XZUFM.137111$PlBb.67508@fx42.iad>
X-Complaints-To: https://www.astraweb.com/aup
NNTP-Posting-Date: Fri, 25 Aug 2023 03:11:51 UTC
Date: Thu, 24 Aug 2023 23:11:51 -0400
X-Received-Bytes: 29228
 by: Pavel - Fri, 25 Aug 2023 03:11 UTC

Öö Tiib wrote:
> On Thursday, 24 August 2023 at 08:39:04 UTC+3, Pavel wrote:
>> Öö Tiib wrote:
>>> On Tuesday, 22 August 2023 at 05:55:32 UTC+3, Pavel wrote:
>>>> Öö Tiib wrote:
>>>>> On Monday, 21 August 2023 at 01:02:21 UTC+3, Pavel wrote:
>>>>>> Öö Tiib wrote:
>>>>>>> On Sunday, 20 August 2023 at 21:13:01 UTC+3, Pavel wrote:
>>>>>>>
>>>>>>>> 1. Ensure all objects have a common base class (say, it's B)
>>>>>>>
>>>>>>> Not needed.
>>>>>>>
>>>>>>>> 2. create an abstract class Visitor with an abstract method doOp with an
>>>>>>>> arg of type [ref to] B.
>>>>>>>
>>>>>>> Nope, pile of overloads of doOp one for each type processed.
>>>>>>
>>>>>> This would render the pattern useless as has no advantage over adding a
>>>>>> virtual method to do the op. The rationale of the pattern is to permit
>>>>>> coding one op in one place.
>>>>>>
>>>>> The Visitor class is that "one place"; doing same operation lets say printing
>>>>> of 50 types in one function results with huge function that is headache
>>>>> not advantage. Separate functions are testable and maintainable.
>>>>>
>>>>>>> Otherwise
>>>>>>> how you process different types differently?
>>>>>> I explained this in the problem statement. "Given [a ref to] any such
>>>>>> object, you are able to
>>>>>> compute its type and/or call a virtual method".
>>>>>
>>>>> IOW you do huge switch typeid ... case static_ cast or have the virtual
>>>>> method (over what we were "gaining advantage") already there?
>>>>
>>>> Even a switch with 30 cases is no worse than 30 methods although switch
>>>> is not always necessary (try to read the above instead of imagining).
>>>>
>>> Visitor is typically used to search, filter, draw or print whole data object
>>> hierarchy, convert to JSON to XML or to tree in GUI.
>> correct
>>> If whole data hierarchy
>>> is small then you get 30 cases. Switch case is worse than virtual methods.
>>
>> *In general* neither is better or worse.
>
> Switch case over type is in general worse than virtual functions. Longer
> function,
Longer than what? Definitely the one function is shorter than the sum of
the length of all the element type hierarchy shims plus concrete visitor
visit overloads.

> bigger cyclomatic complexity,
with good code organization, no bigger than absolutely necessary.

> harder to understand, with good code organization, actually, easier (see my point below about
maintenance.

> harder to
> form confidence that it is valid,
see below in maintenance.

> harder to maintain,
actually, easier to maintain. For using that GoF / wiki DD
implementation, non-insignificant amount of scaffolding code has to be
written. Especially in a complex hierarchy, one can easily forget to
write that accept shim for a couple of classes where it is needed. E.g.
if in the hierarchy (or a part thereof) is "(B, C, D) > A" (> meaning
inheritance), imagine the op shall do same on A and D but different on B
and C. Isn't it easy to forget to add the accept shim to C (even though
the actual logic visit(C), at which the programmer is likely to focus,
is written all right).

> harder to test and
why?

> also may need more access to implementation details of all types
> involved, breaking encapsulation.
How so? All code is written in the op function that has no access to
internals.

>
>> In particular, as I explained
>> at the beginning, if the operation is decomposed correctly, its behavior
>> on the objects of different types has to be coherent, similar in some
>> way (and maybe more similar than different) and, as such, a significant
>> parts of the context or results of intermediate computations could be
>> shared.
>
> Translating data hierarchy to xml for particular version of particular
> protocol while supporting several such in parallel?
Imagine {ABCD) type hierarchy above is to be translated to XML and B and
C have to become XML elements with some non-trivially computable
attribute atr1 but XML elements produced from A and D don't need it.

> There can be
> intermediate computations shared but all are typically in in visitor
> classes or helpers of those. No one wants the classes in hierarchy
> to know anything about xml whatsoever,
correct but do not see how it is connected to anything I wrote

> nothing to talk about
> particular brand used in particular version of kinds of end-points.
let's not argue with anything I did not say, it's really irritating, I
will gladly give you an example, just explain why {ABCD} above is no good.

>
>> I demonstrated this in my example with red and green borders: a)
>> a condition by area prevents visitor from operating on objects is
>> computed from their property that is orthogonal to their dynamic type;
>> and b) the exact behavior of the operation (red vs green border in the
>> example) depends on a subset of types (which, in general, is not
>> necessarily compact in the hierarchy).
>>
> Your example did not need visitor pattern.
No example "needs" visitor pattern: any problem solved with visitor can
be solved in other ways, e.g. just by adding a virtual method to every
class. But *both* my examples could be perfectly solved with visitor. If
the one-time scaffolding is in place, I am ready to argue it is a good
solution.

>
>>> Think why virtual methods were added? To get rid of switch cases over type.
>> Of course, not. Virtual methods were *used*, with less or greater
>> success, to replace switch statements in event-processing scenarios
>> (like window behavior) (with greater success) or in state machines (with
>> lesser success).
>>
>> But, they were *invented* to implement polymorphic behavior and
>> relatively loose coupling (generally, lesser dependencies) between the
>> code that calls the method and the code that implements the method.
>>
> Same loose coupling is with code that calls function that does switch
> case over type, so that kind of victory wasn't achieved.
There is no such thing as "coupling in general". Any particular
dependency is some kind of coupling. If one has to add
accept(AbstractVisitor) method to the root of the type hierarchy, both
the type hierarchy's interface and implementation become compile-time
dependent on the new operation's interface (AbstractVisitor) (interface
may depend on forward-declaration only in C++, but not the
implementation so the implementation will also "see" N "visit" methods).
Additionally, because every AbstractVisitor depends on (the interface
of) every of (say, M) concrete element types, the Element's interface
implementation becomes dependent on every of M Element types (at least
their forward declarations, in C++). In this implementation, any new
operation adds the dependency, needs recompilation of class hierarchy etc.

If, as in my example, you only have one AbstractVisitor, adding 2nd and
further operations adds zero dependencies, don't require recompilation.

>
>> Obviously, a single switch statement couples everything together and the
>> compilation unit where the switch is depends on every piece of code and
>> every concrete type the switch statement handles -- to the extent its
>> behavior in the operation must differ from that of other types). But
>> this loose coupling is only desirable when the behaviors are severely
>> different.
>>
> I don't follow what you are saying. Different stock markets and other
> financial institutions for example are not severely different in essence,
> but the format of data you are expected to exchange with their servers
> differs massively enough.
Nah, it's the other way around. Say, BankA and BankB may have different
formats of their, say, client-side FIX protocol. But, they likely both
talk to NYSE using NYSE FIX/FAST and OATS reporting in exactly same or
almost same format.

Also, who needs to write an app that puts BankA and BankB to the same
hierarchy? It's unlinkely that it's one of BankA or BankB. More likely,
some regulatory agency or an exchange or settlement firm (hereinafter
*an outside firm*). For the purpose of the outside firm, the formats
it's interested in to operate on are likely the formats it uses to
communicate with those Banks (i.e. same or with small customizations). A
drastically different formats that BankA and B use to communicate with
their clients will unlikely be needed by an exchange (they could be
needed by a surveillance agency; but then "my" code would become
respectively simpler, *always staying simpler* than the correspondent
GoF code).


Click here to read the complete article
Re: What is visitor pattern?

<uc9696$3rp9i$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1182&group=comp.lang.c%2B%2B#1182

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bonita.Montero@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c++
Subject: Re: What is visitor pattern?
Date: Fri, 25 Aug 2023 05:13:44 +0200
Organization: A noiseless patient Spider
Lines: 10
Message-ID: <uc9696$3rp9i$1@dont-email.me>
References: <331cb164-e6b3-4f9b-af8d-ee933abd79b7n@googlegroups.com>
<uIsEM.123835$QQFb.6082@fx38.iad> <ubuoig$1ons4$1@dont-email.me>
<AXVEM.568386$SuUf.28925@fx14.iad> <uc1b4g$292ev$1@dont-email.me>
<LzWEM.65654$VPEa.6307@fx33.iad> <uc29p5$2dgb7$1@dont-email.me>
<niCFM.897824$GMN3.379171@fx16.iad> <uc703b$3cer6$1@dont-email.me>
<gcSFM.312013$Fgta.22420@fx10.iad>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 25 Aug 2023 03:13:42 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="b587a1518818f1bb298ac3db843a8302";
logging-data="4056370"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+e06OKNkZAcBLyXAzC3etD46EN7Xdefqg="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:ycqVnQhojrOTPGWS4hOBaq5bjLU=
In-Reply-To: <gcSFM.312013$Fgta.22420@fx10.iad>
Content-Language: de-DE
 by: Bonita Montero - Fri, 25 Aug 2023 03:13 UTC

Am 25.08.2023 um 02:02 schrieb Pavel:

> Are you saying that, for whatever cause (like making Visitor more
> IoC-ish) you are willing to drastically narrow the class of problems
> that the pattern commonly-known as Visitor is believed to solve?

I suggested a way to make the vistitor pattern implementable with much
less code and more maintainable. The visitor neither need an addtional
base-class and implementation class.

Pages:123
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor