Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. To singleton or not to singleton, that is the question....
QtWS25 Last Chance

To singleton or not to singleton, that is the question....

Scheduled Pinned Locked Moved Solved C++ Gurus
23 Posts 4 Posters 2.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JonB
    wrote on 6 Nov 2024, 13:09 last edited by JonB 11 Jun 2024, 13:10
    #1

    It's 2024. I use C++ 17. Once and for all I want to put to bed the "best" or "preferred" way to have a set of "global" functions. By which I mean can be called from any module, without passing something into code there to allow it to access such.

    The pattern I have picked and written is the following with singleton:

    #ifndef UTILS_H
    #define UTILS_H
    
    #include <algorithm>
    #include <random>
    
    class RandomNumber
    {
    public:
        static RandomNumber& instance()
        {
            static RandomNumber singleton;
            return singleton;
        }
    
        static std::mt19937 &random_generator();
        template<typename _RAIter>
            void random_shuffle(_RAIter itBegin, _RAIter itEnd) { std::shuffle(itBegin, itEnd, random_generator()); }
        int random_int(int range) const;
    };
    
    #endif // UTILS_H
    

    and

    #include "utils.h"
    
    /*static*/ std::mt19937 &RandomNumber::random_generator()
    {
        static std::random_device rd;
        static std::mt19937 gen(rd());
        return gen;
    }
    
    int RandomNumber::random_int(int range) const
    {
        std::uniform_int_distribution<> distr(0, range);
        return distr(random_generator());
    }
    

    So that any outside world module can #include "utils.h" and then call like

    RandomNumber::instance().random_shuffle(....)
    RandomNumber::instance().random_int(10)
    

    Can we confirm this is still regarded as the "best" pattern for this kind of thing as of now? If so I will mark this as solution and can relax happily....

    (Btw, I am aware there is debate about concurrency/threads for this pattern. That is not my concern here.)

    J 1 Reply Last reply 6 Nov 2024, 13:11
    0
    • J JonB
      6 Nov 2024, 13:14

      @jsulm said in To singleton or not to singleton, that is the question....:

      avoid singletons!

      Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

      Why do you need a class here?

      A namespace would be enough.

      Because I don't know how to write/use namespaces in my own code! Can you show me how this could/would be written (and called) the way you suggest, please?

      J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 6 Nov 2024, 13:17 last edited by
      #4

      @JonB

      #ifndef UTILS_H
      #define UTILS_H
      
      #include <algorithm>
      #include <random>
      
      namespace RandomNumber
      {
      
      std::mt19937 &random_generator();
      template<typename _RAIter>  void random_shuffle(_RAIter itBegin, _RAIter itEnd)
      {
          std::shuffle(itBegin, itEnd, random_generator());
      }
         
      int random_int(int range) const;
      
      }
      
      #endif // UTILS_H
      ...
      RandomNumber::random_shuffle(....);
      RandomNumber::random_int(10);
      

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      J 2 Replies Last reply 6 Nov 2024, 13:45
      3
      • J JonB
        6 Nov 2024, 13:09

        It's 2024. I use C++ 17. Once and for all I want to put to bed the "best" or "preferred" way to have a set of "global" functions. By which I mean can be called from any module, without passing something into code there to allow it to access such.

        The pattern I have picked and written is the following with singleton:

        #ifndef UTILS_H
        #define UTILS_H
        
        #include <algorithm>
        #include <random>
        
        class RandomNumber
        {
        public:
            static RandomNumber& instance()
            {
                static RandomNumber singleton;
                return singleton;
            }
        
            static std::mt19937 &random_generator();
            template<typename _RAIter>
                void random_shuffle(_RAIter itBegin, _RAIter itEnd) { std::shuffle(itBegin, itEnd, random_generator()); }
            int random_int(int range) const;
        };
        
        #endif // UTILS_H
        

        and

        #include "utils.h"
        
        /*static*/ std::mt19937 &RandomNumber::random_generator()
        {
            static std::random_device rd;
            static std::mt19937 gen(rd());
            return gen;
        }
        
        int RandomNumber::random_int(int range) const
        {
            std::uniform_int_distribution<> distr(0, range);
            return distr(random_generator());
        }
        

        So that any outside world module can #include "utils.h" and then call like

        RandomNumber::instance().random_shuffle(....)
        RandomNumber::instance().random_int(10)
        

        Can we confirm this is still regarded as the "best" pattern for this kind of thing as of now? If so I will mark this as solution and can relax happily....

        (Btw, I am aware there is debate about concurrency/threads for this pattern. That is not my concern here.)

        J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 6 Nov 2024, 13:11 last edited by
        #2

        @JonB Why do you need a class here?
        A namespace would be enough. No need for a class, an object and singleton (avoid singletons!).

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        J 1 Reply Last reply 6 Nov 2024, 13:14
        0
        • J jsulm
          6 Nov 2024, 13:11

          @JonB Why do you need a class here?
          A namespace would be enough. No need for a class, an object and singleton (avoid singletons!).

          J Offline
          J Offline
          JonB
          wrote on 6 Nov 2024, 13:14 last edited by JonB 11 Jun 2024, 13:16
          #3

          @jsulm said in To singleton or not to singleton, that is the question....:

          avoid singletons!

          Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

          Why do you need a class here?

          A namespace would be enough.

          Because I don't know how to write/use namespaces in my own code! Can you show me how this could/would be written (and called) the way you suggest, please?

          J S 2 Replies Last reply 6 Nov 2024, 13:17
          0
          • J JonB
            6 Nov 2024, 13:14

            @jsulm said in To singleton or not to singleton, that is the question....:

            avoid singletons!

            Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

            Why do you need a class here?

            A namespace would be enough.

            Because I don't know how to write/use namespaces in my own code! Can you show me how this could/would be written (and called) the way you suggest, please?

            J Offline
            J Offline
            jsulm
            Lifetime Qt Champion
            wrote on 6 Nov 2024, 13:17 last edited by
            #4

            @JonB

            #ifndef UTILS_H
            #define UTILS_H
            
            #include <algorithm>
            #include <random>
            
            namespace RandomNumber
            {
            
            std::mt19937 &random_generator();
            template<typename _RAIter>  void random_shuffle(_RAIter itBegin, _RAIter itEnd)
            {
                std::shuffle(itBegin, itEnd, random_generator());
            }
               
            int random_int(int range) const;
            
            }
            
            #endif // UTILS_H
            ...
            RandomNumber::random_shuffle(....);
            RandomNumber::random_int(10);
            

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            J 2 Replies Last reply 6 Nov 2024, 13:45
            3
            • J jsulm
              6 Nov 2024, 13:17

              @JonB

              #ifndef UTILS_H
              #define UTILS_H
              
              #include <algorithm>
              #include <random>
              
              namespace RandomNumber
              {
              
              std::mt19937 &random_generator();
              template<typename _RAIter>  void random_shuffle(_RAIter itBegin, _RAIter itEnd)
              {
                  std::shuffle(itBegin, itEnd, random_generator());
              }
                 
              int random_int(int range) const;
              
              }
              
              #endif // UTILS_H
              ...
              RandomNumber::random_shuffle(....);
              RandomNumber::random_int(10);
              
              J Offline
              J Offline
              JonB
              wrote on 6 Nov 2024, 13:45 last edited by JonB 11 Jun 2024, 13:46
              #5

              @jsulm
              Oh! Well if I had known it was that simple I would have tried it! :) I have changed my code to your namespace way (as you wrote, had to remove the static from random_generator() function) and it all works fine :)

              Let's go through a few things then:

              (avoid singletons!)

              Well, your way is just "global" functions with a namespace tagged on to make it look a bit fancier :) We are also told to avoid global functions....!

              I may have been thinking about if I needed to do some initialization stuff to use it. With singleton/class you still have a constructor where I could do that (not in my example, but maybe another), can't do that with namespace.

              On the same sort of level, if I had needed some member variables I could have them; with namespace they would have to be global variables. And that would also lead to problems with when any initialization of them occurred, where burying them in an instance means I can be sure they are not performed till the instance is first called for.

              Also with a class I can declare variables or methods public or private. namespace does not have that (all is public, you have to wrap inside a second, nested, anonymous namespace to achieve private).

              So would it be that this example works fine without class/singleton but another case might not?

              When did C++ have namespaces? If it's all this simple why the endless debates and examples of using singletons for this sort of thing?

              J 1 Reply Last reply 6 Nov 2024, 13:57
              0
              • J jsulm
                6 Nov 2024, 13:17

                @JonB

                #ifndef UTILS_H
                #define UTILS_H
                
                #include <algorithm>
                #include <random>
                
                namespace RandomNumber
                {
                
                std::mt19937 &random_generator();
                template<typename _RAIter>  void random_shuffle(_RAIter itBegin, _RAIter itEnd)
                {
                    std::shuffle(itBegin, itEnd, random_generator());
                }
                   
                int random_int(int range) const;
                
                }
                
                #endif // UTILS_H
                ...
                RandomNumber::random_shuffle(....);
                RandomNumber::random_int(10);
                
                J Offline
                J Offline
                JonB
                wrote on 6 Nov 2024, 13:57 last edited by JonB 11 Jun 2024, 13:58
                #6

                @jsulm
                P.S. Additional implementation question/style with namespace.

                I rewrote my code your way, leaving the function body definitions inside the .cpp via

                int RandomNumber::random_int() { }
                ...
                

                i.e. with the RandomNumber:: prefix on everything as it was when it was a class. I see that you can write in the .cpp:

                namespace RandomNumber {
                int random_int() { }
                ...
                }
                

                which you cannot do for class. Which to prefer? I'm actually thinking of sticking with the prefix as if it were a class?

                J 1 Reply Last reply 6 Nov 2024, 13:59
                0
                • J JonB
                  6 Nov 2024, 13:45

                  @jsulm
                  Oh! Well if I had known it was that simple I would have tried it! :) I have changed my code to your namespace way (as you wrote, had to remove the static from random_generator() function) and it all works fine :)

                  Let's go through a few things then:

                  (avoid singletons!)

                  Well, your way is just "global" functions with a namespace tagged on to make it look a bit fancier :) We are also told to avoid global functions....!

                  I may have been thinking about if I needed to do some initialization stuff to use it. With singleton/class you still have a constructor where I could do that (not in my example, but maybe another), can't do that with namespace.

                  On the same sort of level, if I had needed some member variables I could have them; with namespace they would have to be global variables. And that would also lead to problems with when any initialization of them occurred, where burying them in an instance means I can be sure they are not performed till the instance is first called for.

                  Also with a class I can declare variables or methods public or private. namespace does not have that (all is public, you have to wrap inside a second, nested, anonymous namespace to achieve private).

                  So would it be that this example works fine without class/singleton but another case might not?

                  When did C++ have namespaces? If it's all this simple why the endless debates and examples of using singletons for this sort of thing?

                  J Offline
                  J Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on 6 Nov 2024, 13:57 last edited by
                  #7

                  @JonB said in To singleton or not to singleton, that is the question....:

                  agged on to make it look a bit fancier

                  Not only! Using namespaces you're avoiding name collisions. And what does "global functions" mean here? If you include a C header with functions you also have "global functions". What you should avoid are global class instances/objects.

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  J 1 Reply Last reply 6 Nov 2024, 14:02
                  0
                  • J JonB
                    6 Nov 2024, 13:57

                    @jsulm
                    P.S. Additional implementation question/style with namespace.

                    I rewrote my code your way, leaving the function body definitions inside the .cpp via

                    int RandomNumber::random_int() { }
                    ...
                    

                    i.e. with the RandomNumber:: prefix on everything as it was when it was a class. I see that you can write in the .cpp:

                    namespace RandomNumber {
                    int random_int() { }
                    ...
                    }
                    

                    which you cannot do for class. Which to prefer? I'm actually thinking of sticking with the prefix as if it were a class?

                    J Offline
                    J Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on 6 Nov 2024, 13:59 last edited by
                    #8

                    @JonB said in To singleton or not to singleton, that is the question....:

                    which you cannot do for class

                    You can put everything into namespaces, including classes. Or did I misunderstand you?

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    J 1 Reply Last reply 6 Nov 2024, 14:07
                    0
                    • J jsulm
                      6 Nov 2024, 13:57

                      @JonB said in To singleton or not to singleton, that is the question....:

                      agged on to make it look a bit fancier

                      Not only! Using namespaces you're avoiding name collisions. And what does "global functions" mean here? If you include a C header with functions you also have "global functions". What you should avoid are global class instances/objects.

                      J Offline
                      J Offline
                      JonB
                      wrote on 6 Nov 2024, 14:02 last edited by
                      #9

                      @jsulm said in To singleton or not to singleton, that is the question....:

                      Using namespaces you're avoiding name collisions.

                      namespace FooNamespace {
                          void bar() {}
                      }
                      

                      versus

                      void FooNamespace_bar() {}
                      

                      There really ain't much difference. That's why I say namespace is just a "prettier" way of writing what is still a global function, the two ways avoid collisions in a not totally dissimilar way!

                      1 Reply Last reply
                      0
                      • J jsulm
                        6 Nov 2024, 13:59

                        @JonB said in To singleton or not to singleton, that is the question....:

                        which you cannot do for class

                        You can put everything into namespaces, including classes. Or did I misunderstand you?

                        J Offline
                        J Offline
                        JonB
                        wrote on 6 Nov 2024, 14:07 last edited by JonB 11 Jun 2024, 14:47
                        #10

                        @jsulm said in To singleton or not to singleton, that is the question....:

                        You can put everything into namespaces, including classes. Or did I misunderstand you?

                        You do misunderstand. Please read again what I wrote in that question so I don't need to write out a full example again (though I will if you cannot get it). The question is about the fact that you can "wrap" the whole of your cpp file (note: asking about the .cpp not the .h) implementation inside a single namespace Foo { ..... all the body of the .cpp stuff without writing prefix Foo:: ... } instead of writing each of your functions as Foo::bar(). You have to to do the latter if it's class Foo. You can choose to do the same versus wrap in a namespace Foo { ... } if it's namespace Foo. Which do you prefer in your namespace .cpp file function definitions?

                        OK, to type it in: in the .cpp file (I'm not talking about the .h file) for a class Foo we write:

                        void Foo::bar() { ... }
                        
                        void Foo::baz() { ... }
                        

                        We have no choice for a class. This also works if Foo is a namespace instead of a class.

                        For a namespace, but not for a class, we can alternatively write .cpp as:

                        namespace Foo {
                        
                        void bar() { ... }
                        
                        void baz() { ... }
                        
                        }
                        

                        to drop the Foo:: prefix against each definition. Do you prefer this for namespaces, or the same Foo:: prefix way as required for classes?

                        J 1 Reply Last reply 7 Nov 2024, 06:07
                        0
                        • J JonB
                          6 Nov 2024, 14:07

                          @jsulm said in To singleton or not to singleton, that is the question....:

                          You can put everything into namespaces, including classes. Or did I misunderstand you?

                          You do misunderstand. Please read again what I wrote in that question so I don't need to write out a full example again (though I will if you cannot get it). The question is about the fact that you can "wrap" the whole of your cpp file (note: asking about the .cpp not the .h) implementation inside a single namespace Foo { ..... all the body of the .cpp stuff without writing prefix Foo:: ... } instead of writing each of your functions as Foo::bar(). You have to to do the latter if it's class Foo. You can choose to do the same versus wrap in a namespace Foo { ... } if it's namespace Foo. Which do you prefer in your namespace .cpp file function definitions?

                          OK, to type it in: in the .cpp file (I'm not talking about the .h file) for a class Foo we write:

                          void Foo::bar() { ... }
                          
                          void Foo::baz() { ... }
                          

                          We have no choice for a class. This also works if Foo is a namespace instead of a class.

                          For a namespace, but not for a class, we can alternatively write .cpp as:

                          namespace Foo {
                          
                          void bar() { ... }
                          
                          void baz() { ... }
                          
                          }
                          

                          to drop the Foo:: prefix against each definition. Do you prefer this for namespaces, or the same Foo:: prefix way as required for classes?

                          J Offline
                          J Offline
                          jsulm
                          Lifetime Qt Champion
                          wrote on 7 Nov 2024, 06:07 last edited by
                          #11

                          @JonB said in To singleton or not to singleton, that is the question....:

                          Which do you prefer in your namespace .cpp file function definitions?

                          For function definitions I prefer

                          namespace Foo {
                          
                          void bar() { ... }
                          
                          void baz() { ... }
                          
                          }
                          

                          But if I use the functions I prefer to keep Foo:: prefix instead of using "using Foo;" directives.

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          JoeCFDJ 1 Reply Last reply 8 Nov 2024, 12:29
                          1
                          • J JonB has marked this topic as solved on 7 Nov 2024, 08:55
                          • J JonB
                            6 Nov 2024, 13:14

                            @jsulm said in To singleton or not to singleton, that is the question....:

                            avoid singletons!

                            Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

                            Why do you need a class here?

                            A namespace would be enough.

                            Because I don't know how to write/use namespaces in my own code! Can you show me how this could/would be written (and called) the way you suggest, please?

                            S Offline
                            S Offline
                            SimonSchroeder
                            wrote on 7 Nov 2024, 09:11 last edited by
                            #12

                            @JonB said in To singleton or not to singleton, that is the question....:

                            Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

                            The original design patterns book just had a look at a lot of existing source code and unified the patterns that occured over and over again. And they gave names to these patterns. This means that a singleton is an obvious solution to a problem such that a lot of people came up with the idea. It does not mean it is the best solution. My understanding is that singletons should be avoided because they make your code untestable (here is the long version with explanations how to replace singletons: https://youtu.be/f46jmm7r8Yg?si=0lkErLBA2Xqj5rU6).

                            @JonB said in To singleton or not to singleton, that is the question....:

                            We are also told to avoid global functions....!

                            Well, this advice is most likely related to the purest form of object oriented programming. In OOP there are only objects and no free standing functions. However, C++ is a multiparadigm language. Bjarne Stroustrup himself advocates to use the best tool for the solution. OOP is not always the best tool. "When all you have is a hammer, everything looks like a nail." But, C++ has a hammer, a wrench, etc. Use these tools where appropriate. BTW, some people in the C++ community are moving away from OOP. "Data-oriented design" and "value-oriented programming" are the new buzzwords. E.g. algorithms are not objects. Does it make any sense to write Math.sqrt(x); in Java? Or is it better if you can write sqrt(x);? I prefer the latter.

                            @JonB said in To singleton or not to singleton, that is the question....:

                            Also with a class I can declare variables or methods public or private. namespace does not have that (all is public, you have to wrap inside a second, nested, anonymous namespace to achieve private).

                            With namespaces everything inside the header is public and everything that can only be found in the .cpp file is private. Using an unnamed namespace or marking free functions static just hides them during link-time as well. And you should really avoid global variables (i.e. also any kind of variables inside of namespaces). There is the all too common problem of the initialization order. Instead the workaround would be to use a function int &getMyVar() { static int myVar; return myVar; }. Once they have matured, modules will be the correct answer instead of namespaces. You have to explicitly export any functions or variables (i.e. make them 'public').

                            @JonB said in To singleton or not to singleton, that is the question....:

                            So would it be that this example works fine without class/singleton but another case might not?

                            Yes, in this case a singleton is the suboptimal solution. There are other cases where they make more sense.

                            J 1 Reply Last reply 7 Nov 2024, 09:46
                            1
                            • S SimonSchroeder
                              7 Nov 2024, 09:11

                              @JonB said in To singleton or not to singleton, that is the question....:

                              Sigh, that's what I mean, I still find plenty out there advocating using singletons and now you say avoid, that is what I feared when I thought I had got to grips with it... ;-)

                              The original design patterns book just had a look at a lot of existing source code and unified the patterns that occured over and over again. And they gave names to these patterns. This means that a singleton is an obvious solution to a problem such that a lot of people came up with the idea. It does not mean it is the best solution. My understanding is that singletons should be avoided because they make your code untestable (here is the long version with explanations how to replace singletons: https://youtu.be/f46jmm7r8Yg?si=0lkErLBA2Xqj5rU6).

                              @JonB said in To singleton or not to singleton, that is the question....:

                              We are also told to avoid global functions....!

                              Well, this advice is most likely related to the purest form of object oriented programming. In OOP there are only objects and no free standing functions. However, C++ is a multiparadigm language. Bjarne Stroustrup himself advocates to use the best tool for the solution. OOP is not always the best tool. "When all you have is a hammer, everything looks like a nail." But, C++ has a hammer, a wrench, etc. Use these tools where appropriate. BTW, some people in the C++ community are moving away from OOP. "Data-oriented design" and "value-oriented programming" are the new buzzwords. E.g. algorithms are not objects. Does it make any sense to write Math.sqrt(x); in Java? Or is it better if you can write sqrt(x);? I prefer the latter.

                              @JonB said in To singleton or not to singleton, that is the question....:

                              Also with a class I can declare variables or methods public or private. namespace does not have that (all is public, you have to wrap inside a second, nested, anonymous namespace to achieve private).

                              With namespaces everything inside the header is public and everything that can only be found in the .cpp file is private. Using an unnamed namespace or marking free functions static just hides them during link-time as well. And you should really avoid global variables (i.e. also any kind of variables inside of namespaces). There is the all too common problem of the initialization order. Instead the workaround would be to use a function int &getMyVar() { static int myVar; return myVar; }. Once they have matured, modules will be the correct answer instead of namespaces. You have to explicitly export any functions or variables (i.e. make them 'public').

                              @JonB said in To singleton or not to singleton, that is the question....:

                              So would it be that this example works fine without class/singleton but another case might not?

                              Yes, in this case a singleton is the suboptimal solution. There are other cases where they make more sense.

                              J Offline
                              J Offline
                              JonB
                              wrote on 7 Nov 2024, 09:46 last edited by JonB 11 Jul 2024, 09:51
                              #13

                              @SimonSchroeder
                              Yep, all good, a few comments from me.

                              For the global stuff, @jsulm made a good point when he said "What you should avoid are global class instances/objects". I agree global functions are not so harmful.

                              Does it make any sense to write Math.sqrt(x); in Java? Or is it better if you can write sqrt(x);? I prefer the latter.

                              I think many years of C# programming in the past makes me think of everything having to be the former not the latter. There are no "free functions", everything must be in some class. Maybe same as Java, I don't know. And of course it's actually std::sqrt unless you are using std.

                              With namespaces everything inside the header is public and everything that can only be found in the .cpp file is private. Using an unnamed namespace or marking free functions static just hides them during link-time as well

                              Ah, this is good! I was thinking I had to declare all my functions inside the namespace in the header header as I would have to do for class but everything being public without any private keyword. To test I tried writing void RandomNumber::foo() { } in the .cpp (nothing in the .h) but that gives me ... should have been declared inside ‘RandomNumber’. To achieve a .cpp-only function I found I had to use the "alternative" syntax of:

                              namespace RandomNumber
                              {
                              void foo() {}
                              }
                              

                              or I could "add to" the namespace first in the .cpp and use:

                              // top of file
                              namespace RandomNumber
                              {
                                  void RandomNumber::foo();
                              }
                              ...
                              // later on
                              void RandomNumber::foo() {}
                              

                              As an aside, this is just what I wish most that C++ had for classes. One of the things I hate most is that you have to put all your method declarations in the header file. I loathe having to put the private ones there, and consequently as well having to put in whatever #includes into the .h just to support anything in private. If classes could have their privates in the .cpp only as per the second way above it would be so much better, but I know you can't have "partial" classes in C++ which you can augment e.g. in the .cpp.

                              workaround would be to use a function int &getMyVar() { static int myVar; return myVar; }

                              Yes, that is what my original singleton pattern code used for its static RandomNumber& instance() method.

                              @SimonSchroeder said in To singleton or not to singleton, that is the question....:

                              Yes, in this case a singleton is the suboptimal solution. There are other cases where they make more sense.

                              Agreed. I have changed all my stuff for this case to namespace, I have learned a lot about them so I am confident now going forward. I will worry about "other cases", perhaps when what I need really is a class for some reason, as and when I encounter them.

                              J 2 Replies Last reply 7 Nov 2024, 09:51
                              0
                              • J JonB
                                7 Nov 2024, 09:46

                                @SimonSchroeder
                                Yep, all good, a few comments from me.

                                For the global stuff, @jsulm made a good point when he said "What you should avoid are global class instances/objects". I agree global functions are not so harmful.

                                Does it make any sense to write Math.sqrt(x); in Java? Or is it better if you can write sqrt(x);? I prefer the latter.

                                I think many years of C# programming in the past makes me think of everything having to be the former not the latter. There are no "free functions", everything must be in some class. Maybe same as Java, I don't know. And of course it's actually std::sqrt unless you are using std.

                                With namespaces everything inside the header is public and everything that can only be found in the .cpp file is private. Using an unnamed namespace or marking free functions static just hides them during link-time as well

                                Ah, this is good! I was thinking I had to declare all my functions inside the namespace in the header header as I would have to do for class but everything being public without any private keyword. To test I tried writing void RandomNumber::foo() { } in the .cpp (nothing in the .h) but that gives me ... should have been declared inside ‘RandomNumber’. To achieve a .cpp-only function I found I had to use the "alternative" syntax of:

                                namespace RandomNumber
                                {
                                void foo() {}
                                }
                                

                                or I could "add to" the namespace first in the .cpp and use:

                                // top of file
                                namespace RandomNumber
                                {
                                    void RandomNumber::foo();
                                }
                                ...
                                // later on
                                void RandomNumber::foo() {}
                                

                                As an aside, this is just what I wish most that C++ had for classes. One of the things I hate most is that you have to put all your method declarations in the header file. I loathe having to put the private ones there, and consequently as well having to put in whatever #includes into the .h just to support anything in private. If classes could have their privates in the .cpp only as per the second way above it would be so much better, but I know you can't have "partial" classes in C++ which you can augment e.g. in the .cpp.

                                workaround would be to use a function int &getMyVar() { static int myVar; return myVar; }

                                Yes, that is what my original singleton pattern code used for its static RandomNumber& instance() method.

                                @SimonSchroeder said in To singleton or not to singleton, that is the question....:

                                Yes, in this case a singleton is the suboptimal solution. There are other cases where they make more sense.

                                Agreed. I have changed all my stuff for this case to namespace, I have learned a lot about them so I am confident now going forward. I will worry about "other cases", perhaps when what I need really is a class for some reason, as and when I encounter them.

                                J Offline
                                J Offline
                                jsulm
                                Lifetime Qt Champion
                                wrote on 7 Nov 2024, 09:51 last edited by
                                #14

                                @JonB said in To singleton or not to singleton, that is the question....:

                                should have been declared inside ‘RandomNumber’

                                This should work (in .cpp):

                                void someHelperFunction()
                                {
                                }
                                
                                namespace RandomNumber
                                {
                                    void foo()
                                    {
                                        someHelperFunction();
                                    }
                                }
                                

                                https://forum.qt.io/topic/113070/qt-code-of-conduct

                                J 1 Reply Last reply 7 Nov 2024, 09:57
                                0
                                • J JonB
                                  7 Nov 2024, 09:46

                                  @SimonSchroeder
                                  Yep, all good, a few comments from me.

                                  For the global stuff, @jsulm made a good point when he said "What you should avoid are global class instances/objects". I agree global functions are not so harmful.

                                  Does it make any sense to write Math.sqrt(x); in Java? Or is it better if you can write sqrt(x);? I prefer the latter.

                                  I think many years of C# programming in the past makes me think of everything having to be the former not the latter. There are no "free functions", everything must be in some class. Maybe same as Java, I don't know. And of course it's actually std::sqrt unless you are using std.

                                  With namespaces everything inside the header is public and everything that can only be found in the .cpp file is private. Using an unnamed namespace or marking free functions static just hides them during link-time as well

                                  Ah, this is good! I was thinking I had to declare all my functions inside the namespace in the header header as I would have to do for class but everything being public without any private keyword. To test I tried writing void RandomNumber::foo() { } in the .cpp (nothing in the .h) but that gives me ... should have been declared inside ‘RandomNumber’. To achieve a .cpp-only function I found I had to use the "alternative" syntax of:

                                  namespace RandomNumber
                                  {
                                  void foo() {}
                                  }
                                  

                                  or I could "add to" the namespace first in the .cpp and use:

                                  // top of file
                                  namespace RandomNumber
                                  {
                                      void RandomNumber::foo();
                                  }
                                  ...
                                  // later on
                                  void RandomNumber::foo() {}
                                  

                                  As an aside, this is just what I wish most that C++ had for classes. One of the things I hate most is that you have to put all your method declarations in the header file. I loathe having to put the private ones there, and consequently as well having to put in whatever #includes into the .h just to support anything in private. If classes could have their privates in the .cpp only as per the second way above it would be so much better, but I know you can't have "partial" classes in C++ which you can augment e.g. in the .cpp.

                                  workaround would be to use a function int &getMyVar() { static int myVar; return myVar; }

                                  Yes, that is what my original singleton pattern code used for its static RandomNumber& instance() method.

                                  @SimonSchroeder said in To singleton or not to singleton, that is the question....:

                                  Yes, in this case a singleton is the suboptimal solution. There are other cases where they make more sense.

                                  Agreed. I have changed all my stuff for this case to namespace, I have learned a lot about them so I am confident now going forward. I will worry about "other cases", perhaps when what I need really is a class for some reason, as and when I encounter them.

                                  J Offline
                                  J Offline
                                  jsulm
                                  Lifetime Qt Champion
                                  wrote on 7 Nov 2024, 09:53 last edited by
                                  #15

                                  @JonB said in To singleton or not to singleton, that is the question....:

                                  consequently as well having to put in whatever #includes into the .h just to support anything in private

                                  In case of pointers you can avoid the includes by using forward declarations.

                                  Often d pointer pattern is used to hide implementation details and keep binary compatibility while changing internal implementation.

                                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  J 1 Reply Last reply 7 Nov 2024, 10:02
                                  0
                                  • J jsulm
                                    7 Nov 2024, 09:51

                                    @JonB said in To singleton or not to singleton, that is the question....:

                                    should have been declared inside ‘RandomNumber’

                                    This should work (in .cpp):

                                    void someHelperFunction()
                                    {
                                    }
                                    
                                    namespace RandomNumber
                                    {
                                        void foo()
                                        {
                                            someHelperFunction();
                                        }
                                    }
                                    
                                    J Offline
                                    J Offline
                                    JonB
                                    wrote on 7 Nov 2024, 09:57 last edited by JonB 11 Jul 2024, 09:57
                                    #16

                                    @jsulm
                                    Hi, not sure if you are adding something here? I wrote above that, with nothing in the .h file, you can indeed put in the .cpp

                                    namespace RandomNumber
                                    {
                                        void foo() { ... }
                                    }
                                    

                                    What I said I found you cannot do is

                                    void RandomNumber::foo() { ... }
                                    

                                    For that, if you are not going to put

                                    namespace RandomNumber
                                    {
                                        void foo();
                                    }
                                    

                                    in the .h (because you want to only use it privately) then I found you can/must add it in the .cpp --- this adding to the namespace declarations from the .h --- before defining it via void RandomNumber::foo() { ... }.

                                    [I never had a question about some global/free someHelperFunction() function.]

                                    S 1 Reply Last reply 8 Nov 2024, 07:50
                                    0
                                    • J jsulm
                                      7 Nov 2024, 09:53

                                      @JonB said in To singleton or not to singleton, that is the question....:

                                      consequently as well having to put in whatever #includes into the .h just to support anything in private

                                      In case of pointers you can avoid the includes by using forward declarations.

                                      Often d pointer pattern is used to hide implementation details and keep binary compatibility while changing internal implementation.

                                      J Offline
                                      J Offline
                                      JonB
                                      wrote on 7 Nov 2024, 10:02 last edited by JonB 11 Jul 2024, 10:03
                                      #17

                                      @jsulm said in To singleton or not to singleton, that is the question....:

                                      In case of pointers you can avoid the includes by using forward declarations.

                                      Of course, and I do sometimes do that to avoid being forced to pull in a full #include. But when, say, you have a whole load of private methods in a class and they use types (copy or reference) as parameters/returns which are either from your own "internal" types or from external types you get forced to have the full #includes in the .h even if only relevant to your private methods. I hate that.

                                      1 Reply Last reply
                                      0
                                      • J JonB
                                        7 Nov 2024, 09:57

                                        @jsulm
                                        Hi, not sure if you are adding something here? I wrote above that, with nothing in the .h file, you can indeed put in the .cpp

                                        namespace RandomNumber
                                        {
                                            void foo() { ... }
                                        }
                                        

                                        What I said I found you cannot do is

                                        void RandomNumber::foo() { ... }
                                        

                                        For that, if you are not going to put

                                        namespace RandomNumber
                                        {
                                            void foo();
                                        }
                                        

                                        in the .h (because you want to only use it privately) then I found you can/must add it in the .cpp --- this adding to the namespace declarations from the .h --- before defining it via void RandomNumber::foo() { ... }.

                                        [I never had a question about some global/free someHelperFunction() function.]

                                        S Offline
                                        S Offline
                                        SimonSchroeder
                                        wrote on 8 Nov 2024, 07:50 last edited by
                                        #18

                                        @JonB said in To singleton or not to singleton, that is the question....:

                                        then I found you can/must add it in the .cpp --- this adding to the namespace declarations from the .h

                                        One of the nice things about namespaces is that you can reopen them as often as you want to. There are even a few cases where you are supposed to add something to namespace std.

                                        @JonB said in To singleton or not to singleton, that is the question....:

                                        they use types (copy or reference) as parameters/returns

                                        Just like pointers, references are also find and just need forward declarations. If your class has more than one or two member variables (of built-in type) it is most likely cheaper to use a reference instead of a copy. I only have very few cases where I'd want a copy of an object. That being said, I just noticed that I don't know if r-value references && also work with forward declarations. Does anybody know?

                                        JoeCFDJ 1 Reply Last reply 8 Nov 2024, 12:26
                                        0
                                        • S SimonSchroeder
                                          8 Nov 2024, 07:50

                                          @JonB said in To singleton or not to singleton, that is the question....:

                                          then I found you can/must add it in the .cpp --- this adding to the namespace declarations from the .h

                                          One of the nice things about namespaces is that you can reopen them as often as you want to. There are even a few cases where you are supposed to add something to namespace std.

                                          @JonB said in To singleton or not to singleton, that is the question....:

                                          they use types (copy or reference) as parameters/returns

                                          Just like pointers, references are also find and just need forward declarations. If your class has more than one or two member variables (of built-in type) it is most likely cheaper to use a reference instead of a copy. I only have very few cases where I'd want a copy of an object. That being said, I just noticed that I don't know if r-value references && also work with forward declarations. Does anybody know?

                                          JoeCFDJ Offline
                                          JoeCFDJ Offline
                                          JoeCFD
                                          wrote on 8 Nov 2024, 12:26 last edited by
                                          #19

                                          @SimonSchroeder r-value references && work with forward declarations.

                                          1 Reply Last reply
                                          1
                                          • jsulmJ jsulm
                                            7 Nov 2024, 06:07

                                            @JonB said in To singleton or not to singleton, that is the question....:

                                            Which do you prefer in your namespace .cpp file function definitions?

                                            For function definitions I prefer

                                            namespace Foo {
                                            
                                            void bar() { ... }
                                            
                                            void baz() { ... }
                                            
                                            }
                                            

                                            But if I use the functions I prefer to keep Foo:: prefix instead of using "using Foo;" directives.

                                            JoeCFDJ Offline
                                            JoeCFDJ Offline
                                            JoeCFD
                                            wrote on 8 Nov 2024, 12:29 last edited by JoeCFD 11 Aug 2024, 12:52
                                            #20

                                            @jsulm if void baz() is defined in two namespaces, Calling baz() with using "using Foo;" can cause confusing while two namespaces are present at the same place. Therefore, Foo:: prefix is preferred.

                                            namespace Foo1 {
                                            void baz() { ... }
                                            }
                                            
                                            namespace Foo2 {
                                            void baz() { ... }
                                            }
                                            
                                            In another class:
                                            
                                            using Foo1;
                                            using Foo2;
                                            
                                            void AnotheClass::testing()
                                            {
                                                    baz();  // not clear
                                            }
                                            
                                            ===================
                                            
                                            void AnotheClass::testing()
                                            {
                                                    Foo1::baz();  // clear
                                            }
                                            
                                            JonBJ S 2 Replies Last reply 8 Nov 2024, 13:06
                                            0

                                            2/23

                                            6 Nov 2024, 13:11

                                            21 unread
                                            • Login

                                            • Login or register to search.
                                            2 out of 23
                                            • First post
                                              2/23
                                              Last post
                                            0
                                            • Categories
                                            • Recent
                                            • Tags
                                            • Popular
                                            • Users
                                            • Groups
                                            • Search
                                            • Get Qt Extensions
                                            • Unsolved