Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #91307 > unrolled thread

What is visitor pattern?

Started bywij <wyniijj5@gmail.com>
First post2023-08-20 06:55 -0700
Last post2023-08-29 19:27 +0200
Articles 13 on this page of 53 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  What is visitor pattern? wij <wyniijj5@gmail.com> - 2023-08-20 06:55 -0700
    Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-20 07:22 -0700
      Re: What is visitor pattern? wij <wyniijj5@gmail.com> - 2023-08-20 19:24 -0700
      Re: What is visitor pattern? wij <wyniijj5@gmail.com> - 2023-08-27 13:13 -0700
        Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-28 00:13 -0700
          Re: What is visitor pattern? wij <wyniijj5@gmail.com> - 2023-08-28 23:18 -0700
    Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-20 14:12 -0400
      Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-20 13:34 -0700
        Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-20 18:01 -0400
          Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-20 21:12 -0700
            Re: What is visitor pattern? Muttley@dastardlyhq.com - 2023-08-21 06:53 +0000
              Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-21 00:10 -0700
                Re: What is visitor pattern? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-08-26 21:26 -0700
                  Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-26 22:57 -0700
                    Re: What is visitor pattern? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-08-28 15:07 -0700
            Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-21 22:55 -0400
              Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-21 21:56 -0700
                Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-24 01:38 -0400
                  Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-24 04:45 -0700
                    Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-24 23:11 -0400
                      Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-25 07:52 -0700
                        Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-26 00:55 -0400
      Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-21 06:18 +0200
        Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-21 23:28 -0400
          Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-22 05:47 +0200
            Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-22 00:11 -0400
              Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-22 14:30 +0200
                Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-24 01:56 -0400
                  Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-24 09:15 +0200
                    Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-24 20:02 -0400
                      Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-25 05:13 +0200
                        Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-26 01:05 -0400
                          Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 09:24 +0200
                            Re: What is visitor pattern? Muttley@dastardlyhq.com - 2023-08-26 08:01 +0000
                              Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 11:29 +0200
                                Re: What is visitor pattern? Muttley@dastardlyhq.com - 2023-08-26 15:00 +0000
                                  Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 17:08 +0200
                                    Re: What is visitor pattern? Muttley@dastardlyhq.com - 2023-08-26 15:15 +0000
                                      Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 17:24 +0200
                                        Re: What is visitor pattern? Muttley@dastardlyhq.com - 2023-08-26 15:36 +0000
                                          Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 17:39 +0200
                                      Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-26 17:26 +0200
                                  Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-29 21:44 -0400
                            Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-29 22:14 -0400
                              Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-30 06:13 +0200
                                Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-30 23:18 -0400
    Re: What is visitor pattern? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-08-21 01:17 +0200
      Re: What is visitor pattern? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-08-21 01:24 +0200
    Re: What is visitor pattern? Michael S <already5chosen@yahoo.com> - 2023-08-25 05:21 -0700
      Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-25 14:33 +0200
      Re: What is visitor pattern? Öö Tiib <ootiib@hot.ee> - 2023-08-25 08:28 -0700
      Re: What is visitor pattern? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2023-08-26 01:17 -0400
    Re: What is visitor pattern? Bonita Montero <Bonita.Montero@gmail.com> - 2023-08-29 19:27 +0200

Page 3 of 3 — ← Prev page 1 2 [3]


#91445

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-08-26 17:39 +0200
Message-ID<ucd6bp$kol7$1@dont-email.me>
In reply to#91444
Am 26.08.2023 um 17:36 schrieb Muttley@dastardlyhq.com:
> On Sat, 26 Aug 2023 17:24:00 +0200
> Bonita Montero <Bonita.Montero@gmail.com> wrote:
>> Am 26.08.2023 um 17:15 schrieb Muttley@dastardlyhq.com:
>>> On Sat, 26 Aug 2023 17:08:15 +0200
>>> Bonita Montero <Bonita.Montero@gmail.com> wrote:
>>>> Am 26.08.2023 um 17:00 schrieb Muttley@dastardlyhq.com:
>>>>
>>>>> People who say you can have functional programming in C++ don't understand
>>>>> functional programming. Its more than just no cost recursion , its also
>>>>> polymorphism by *VALUE*. ...
>>>>
>>>> That's what I described and you didn't notice it. A function<>-object
>>>> is always polymorphic. I bet you never used function<>-objects in C++.
>>>
>>> Given they're necessary for the STL what do you think?
>>>
>>> Which part of "by value" is confusing you? But if you insist on claiming its
>>> possible show us how you'd do polymorphism for a function with a single int
>>> param for say the values 0, 2, 3, 10 -> 100 and a default.
>>
>> You can't describe what you want and you don't understand function<>
>> -objects. Stick with C.
> 
> Translation: I can't do it because its not possible but don't have the balls
> to admit I was wrong.

Of course I can't do that because your requirements are too diffuse.

> 
> Go back to writing your next piece of lame shit code to post on here in order
> to show off.
> 

[toc] | [prev] | [next] | [standalone]


#91443

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-08-26 17:26 +0200
Message-ID<ucd5k0$kkll$1@dont-email.me>
In reply to#91441
Am 26.08.2023 um 17:15 schrieb Muttley@dastardlyhq.com:
> On Sat, 26 Aug 2023 17:08:15 +0200
> Bonita Montero <Bonita.Montero@gmail.com> wrote:
>> Am 26.08.2023 um 17:00 schrieb Muttley@dastardlyhq.com:
>>
>>> People who say you can have functional programming in C++ don't understand
>>> functional programming. Its more than just no cost recursion , its also
>>> polymorphism by *VALUE*. ...
>>
>> That's what I described and you didn't notice it. A function<>-object
>> is always polymorphic. I bet you never used function<>-objects in C++.
> 
> Given they're necessary for the STL what do you think?
> 
> Which part of "by value" is confusing you? But if you insist on claiming its
> possible show us how you'd do polymorphism for a function with a single int
> param for say the values 0, 2, 3, 10 -> 100 and a default.
> 

Somehow you are also quite disturbed. I wanted to tell nru that the
visitor pattern in C++ can be greatly simplified with a c++11 function<>
object and you are offended by this mere statement that you have to
explain the possibilities of C++11 as insufficient at this point to
put you above me. The therapist that matches you has yet to be born.

[toc] | [prev] | [next] | [standalone]


#91468

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2023-08-29 21:44 -0400
Message-ID<9axHM.112635$JbKe.40455@fx04.iad>
In reply to#91439
Muttley@dastardlyhq.com wrote:
> On Sat, 26 Aug 2023 11:29:34 +0200
> Bonita Montero <Bonita.Montero@gmail.com> wrote:
>> Am 26.08.2023 um 10:01 schrieb Muttley@dastardlyhq.com:
>>
>>> This sort of programming is the equivalent of touchscreens in cars - looks
>>> great and impresses the "Ooo shiny!" crowd but adds little to the main
>>> functionality of the car and just adds needless complexity with more scope
>>> for failure.
>>
>> My solution is less complexity because you don't need to declare
>> a base  class and a derived class. Just declare the parameter as
>> a function object and pass a lambda which is automatically crated.
>> That's for sure at maximally the tenth of the code.
>> You can have functional programming in C++ since 2011. That's a
>> long time you didn't notice its potential.
> 
> People who say you can have functional programming in C++ don't understand
> functional programming. Its more than just no cost recursion , its also
> polymorphism by *VALUE*. That is not and probably never will be possible in
> C++.
> 
Hard to believe but they were thinking of it as recently as Sep 2020, 
see https://wg21.link/p1371r3

But of course, on mutable objects, pattern mathcing loses some 90% of 
its use.

[toc] | [prev] | [next] | [standalone]


#91469

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2023-08-29 22:14 -0400
Message-ID<WBxHM.964727$GMN3.213848@fx16.iad>
In reply to#91425
Bonita Montero wrote:
> Am 26.08.2023 um 07:05 schrieb Pavel:
> 
>> Visitor does not need anything, it simply solves a particular class
>> of  problems that happens to include a structure of objects of 
>> multiple types. Your visitor implementation is invalid if it cannot 
>> solve a valid visitor problem.
> 
> Either I didn't describe the difference to what you imagine correctly
> or you just didn't understand me.
None of the above it is just you are not trying to read.

> In the Visitor pattern, the Visitor
> needs a base class with a virtual method to derive from, and the derived
> object is passed by reference to the Visitor function of the objects
> being visited. 
No. Visitor needs no types. The **problems that Visitor solves** include 
data structures of multiple types. The applicability of Visitor is 
exactly when the programmer is limited to small backward-compatible 
changes to the type hierarchy **given in the problem, not "needed by 
Visitor"**, ideally, no changes at all.

Try to read what's written, not what you want to see.

I will try one more time, in negative terms, in case it makes it easier 
for you to comprehend:

No type hierarchy in the problem -- no need in Visitor in the solution.

Now, "a base class with a virtual method to derive from" are just 
possible implementation details for the type hierarchy, so not 100% 
needed. The type hierarchy could be a variant or another type hierarchy 
where the dynamic type is detectable at run-time. There must be, 
however, a comprehensive type hierarchy for the Visitor to be useful.

What you are trying to demonstrate, on the other hand, is called a 
"higher-order function" in functional programming. And, no, it does not 
need a new name because it already has an industry-standard name.

> However, the derived and the base class are superfluous
> with functional programming. Since C++11 you can simply request a
> function<> object and conveniently you just pass a lambda that when
> called, a temporary function<> object is created that represents the
> interface to the object that can be visited.

[toc] | [prev] | [next] | [standalone]


#91470

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-08-30 06:13 +0200
Message-ID<ucmfll$2k424$1@dont-email.me>
In reply to#91469
Am 30.08.2023 um 04:14 schrieb Pavel:

> No. Visitor needs no types. The **problems that Visitor solves** include 
> data structures of multiple types. The applicability of Visitor is 
> exactly when the programmer is limited to small backward-compatible 
> changes to the type hierarchy **given in the problem, not "needed by 
> Visitor"**, ideally, no changes at all.

You simply don't understand what I wrote.

[toc] | [prev] | [next] | [standalone]


#91477

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2023-08-30 23:18 -0400
Message-ID<LDTHM.472104$xMqa.73253@fx12.iad>
In reply to#91470
Bonita Montero wrote:
> Am 30.08.2023 um 04:14 schrieb Pavel:
> 
>> No. Visitor needs no types. The **problems that Visitor solves** 
>> include data structures of multiple types. The applicability of 
>> Visitor is exactly when the programmer is limited to small 
>> backward-compatible changes to the type hierarchy **given in the 
>> problem, not "needed by Visitor"**, ideally, no changes at all.
> 
> You simply don't understand what I wrote.
> 
Of course if you say so.

[toc] | [prev] | [next] | [standalone]


#91313

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2023-08-21 01:17 +0200
Message-ID<ubu6un$1it4v$1@dont-email.me>
In reply to#91307
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

[toc] | [prev] | [next] | [standalone]


#91314

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2023-08-21 01:24 +0200
Message-ID<ubu7as$1it63$1@dont-email.me>
In reply to#91313
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

[toc] | [prev] | [next] | [standalone]


#91413

FromMichael S <already5chosen@yahoo.com>
Date2023-08-25 05:21 -0700
Message-ID<58893c96-4e95-494f-abc3-3fd6db7b6846n@googlegroups.com>
In reply to#91307
On Sunday, August 20, 2023 at 4:55:56 PM 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. 
> Can anyone explain the visitor pattern or better webpages? 
> probably making the example compile may help, thanks in advance.

After trying, with limited success, to follow the discussion between Öö Tiib and Pavel,
I am coming to conclusion that continued ignorance about Visitor Pattern is best both
for my blood pressure and for my programming skills.

[toc] | [prev] | [next] | [standalone]


#91414

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-08-25 14:33 +0200
Message-ID<uca72c$1aur$1@dont-email.me>
In reply to#91413
Am 25.08.2023 um 14:21 schrieb Michael S:

> After trying, with limited success, to follow the discussion between Öö Tiib and Pavel,
> I am coming to conclusion that continued ignorance about Visitor Pattern is best both
> for my blood pressure and for my programming skills.

I'm not ignore it but I wanted to say that it's easier to implement
it  not with a separate base and dervied class for the visitor but
with a function<>-object. That would save a lot of work and you get
the same performance.

[toc] | [prev] | [next] | [standalone]


#91416

FromÖö Tiib <ootiib@hot.ee>
Date2023-08-25 08:28 -0700
Message-ID<1630c8a7-60a0-4f3e-a8d6-30d75965c004n@googlegroups.com>
In reply to#91413
On Friday, 25 August 2023 at 15:21:43 UTC+3, Michael S wrote:
> On Sunday, August 20, 2023 at 4:55:56 PM 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. 
> > Can anyone explain the visitor pattern or better webpages? 
> > probably making the example compile may help, thanks in advance.
> 
> After trying, with limited success, to follow the discussion between Öö Tiib and Pavel, 
> I am coming to conclusion that continued ignorance about Visitor Pattern is best both 
> for my blood pressure and for my programming skills.
> 
Brilliant decision. Over the decades I have couple times seen visitor misused in
manner that turned the part of code base very hard to maintain. Team members
changed 2 story-point estimation into 20 each time someone realised "but hey,
then we need to change logic in ####Visitor." It had defective dispatch and then
it needed maintenance that made it to grow into kind of cancer no one dared to
touch.

[toc] | [prev] | [next] | [standalone]


#91424

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2023-08-26 01:17 -0400
Message-ID<RVfGM.95673$VzFf.50379@fx03.iad>
In reply to#91413
Michael S wrote:
> On Sunday, August 20, 2023 at 4:55:56 PM 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.
>> Can anyone explain the visitor pattern or better webpages?
>> probably making the example compile may help, thanks in advance.
> 
> After trying, with limited success, to follow the discussion between Öö Tiib and Pavel,
> I am coming to conclusion that continued ignorance about Visitor Pattern is best both
> for my blood pressure and for my programming skills.
> 
You are right, no good deed goes unpunished. I should have known better.

-Pavel

[toc] | [prev] | [next] | [standalone]


#91466

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-08-29 19:27 +0200
Message-ID<ucl9qd$2bhvr$1@dont-email.me>
In reply to#91307
I think that's my final solution. Currently I store the bits in
size_ts and I look up the next set bit with countr_zero which maps
to TZCNT on x64 and according to some small code on godbolt ARM
also has a proper instruction for that.
Resettig the bits for the composites is done by a rotating bit-mask.
If the prime is less than size_t * 8 there's a special case optimi-
zation.

#include <iostream>
#include <vector>
#include <charconv>
#include <string_view>
#include <algorithm>
#include <fstream>
#include <cctype>
#include <cstring>
#include <bit>

#if defined(_MSC_VER)
	#pragma warning(disable: 26495) // uninitialized member
#endif
#if defined(__llvm__)
	#pragma clang diagnostic ignored "-Wdangling-else"
#endif

using namespace std;

int main( int argc, char **argv )
{
	constexpr size_t BUF_SIZE = 0x100000;
	try
	{
		size_t end;
		if( argc < 2 )
			return EXIT_FAILURE;
		char const *sizeStr = argv[1];
		bool hex = sizeStr[0] == '0' && (sizeStr[1] == 'x' || sizeStr[1] == 'X');
		sizeStr += 2 * hex;
		if( from_chars_result fcr = from_chars( sizeStr, sizeStr + strlen( 
sizeStr ), end, !hex ? 10 : 16 ); (bool)fcr.ec || *fcr.ptr )
			return EXIT_FAILURE;
		if( !++end )
			throw bad_alloc();
		using word_t = size_t;
		constexpr size_t BITS = sizeof(word_t) * 8;
		size_t bEnd = (end + BITS - 1) & -(ptrdiff_t)BITS;
		if( bEnd < end )
			throw bad_alloc();
		union ndi_word_t { word_t w; ndi_word_t( word_t w ) : w( w ) {}	};
		using bit_vec = vector<ndi_word_t>;
		using bit_it = bit_vec::iterator;
		bit_vec sieve( (end + BITS - 1) / BITS, (word_t)0xAAAAAAAAAAAAAAAAu );
		ofstream ofs;
		union ndi_t { char c; ndi_t() {} };
		using ndi_vec = vector<ndi_t>;
		constexpr size_t AHEAD = 32;
		ndi_vec printBuf;
		ndi_vec::iterator bufBegin, bufEnd, bufFlush;
		if( argc < 3 || *argv[2] )
		{
			ofs.exceptions( ofstream::failbit | ofstream::badbit );
			ofs.open( argc >= 3 ? argv[2] : "primes.txt", ofstream::trunc );
			printBuf.resize( BUF_SIZE + AHEAD - 1 );
			bufBegin = printBuf.begin();
			bufEnd = bufBegin;
			bufFlush = bufBegin + BUF_SIZE;
		}
		auto print = [&]() { ofs << string_view( &to_address( bufBegin )->c, 
&to_address( bufEnd )->c ); };
		bit_it const pSieveEnd = sieve.end();
		size_t sqr = (ptrdiff_t)ceil( sqrt( (ptrdiff_t)end ) );
		for( size_t p = 2; p < end; )
		{
			if( ofs.is_open() )
			{
				auto [ptr, ec] = to_chars( &bufEnd->c, &to_address( bufEnd + (AHEAD 
- 1) )->c, p );
				if( (bool)ec ) [[unlikely]]
					throw system_error( (int)ec, generic_category(), "converson failed" );
				bufEnd = ptr - &bufBegin->c + bufBegin; // NOP
				bufEnd++->c = '\n';
				if( bufEnd >= bufFlush )
					ofs << string_view( &to_address( bufBegin )->c, &to_address( bufEnd 
)->c ),
					bufEnd = bufBegin;
			}
			if( ++p == end ) [[unlikely]]
				break;
			for( bit_it pSieve = sieve.begin() + p / BITS; ; )
			{
				size_t g = countr_zero( pSieve->w & (word_t)-1 << p % BITS );
				p = (p & -(ptrdiff_t)BITS) + g;
				if( g != BITS )
					break;
				if( ++pSieve == pSieveEnd )
					goto end;
			}
			bit_it pSieve = sieve.begin();
			if( size_t m = p * p; p < sqr )
				if( p >= BITS ) [[likely]]
				{
					word_t mask = rotl( (word_t)-2, m % BITS );
					do
						pSieve[m / BITS].w &= mask,
						mask = rotl( mask, (int)p % BITS ),
						m += p;
					while( m < end );
				}
				else
				{
					pSieve += m / BITS;
					word_t mask = rotl( (word_t)-2, m % BITS );
					do
					{
						word_t punch = -1, oldMask;
						do
							punch &= mask,
							oldMask = mask,
							mask = rotl( mask, (int)p );
						while( mask < oldMask );
						pSieve->w &= punch;
					} while( ++pSieve != pSieveEnd );
				}
		}
	end:
		if( ofs.is_open() )
			print();
		return EXIT_SUCCESS;
	}
	catch( bad_alloc const & )
	{
		cout << "out of memory" << endl;
	}
	catch( ios_base::failure const & )
	{
		cout << "I/O error" << endl;
	}
	catch( system_error const &se )
	{
		cout << se.what() << endl;
	}
}

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.c++


csiph-web