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. Unnecessary const referencing
Qt 6.11 is out! See what's new in the release blog

Unnecessary const referencing

Scheduled Pinned Locked Moved Solved C++ Gurus
18 Posts 7 Posters 3.2k Views 5 Watching
  • 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.
  • sierdzioS sierdzio

    @JonB For POD types, passing a copy (int number, int n) is enough. A const reference in such case is needlessly complicating stuff for no gain at all.

    What I often do for POD types, however, is to pass them as const without a reference (const number, const int n). This offers no advantage in terms of performance but makes it kind of clear that these are input parameters and that they will not change.

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #5

    @sierdzio said in Unnecessary const referencing:

    makes it kind of clear that these are input parameters and that they will not change

    Also, this way, you make sure they are not changed by accident.

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

    1 Reply Last reply
    0
    • sierdzioS sierdzio

      @JonB For POD types, passing a copy (int number, int n) is enough. A const reference in such case is needlessly complicating stuff for no gain at all.

      What I often do for POD types, however, is to pass them as const without a reference (const number, const int n). This offers no advantage in terms of performance but makes it kind of clear that these are input parameters and that they will not change.

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #6

      @sierdzio said in Unnecessary const referencing:

      What I often do for POD types, however, is to pass them as const without a reference (const number, const int n). This offers no advantage in terms of performance but makes it kind of clear that these are input parameters and that they will not change.

      I actually like to do that too, but some code models / compilers actually give you a warning about this

      So I usually end up with the declaration of

      void constArgument(int someArgument);
      

      and a definition of

      void SomeClass::constArgument(const int someArgument)
      {
          qDebug() << someArgument;
      }
      

      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      JonBJ 1 Reply Last reply
      0
      • J.HilkJ J.Hilk

        @sierdzio said in Unnecessary const referencing:

        What I often do for POD types, however, is to pass them as const without a reference (const number, const int n). This offers no advantage in terms of performance but makes it kind of clear that these are input parameters and that they will not change.

        I actually like to do that too, but some code models / compilers actually give you a warning about this

        So I usually end up with the declaration of

        void constArgument(int someArgument);
        

        and a definition of

        void SomeClass::constArgument(const int someArgument)
        {
            qDebug() << someArgument;
        }
        
        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #7

        @J-Hilk
        And why C++ allows you to have a different definition from declaration for this case is beyond me....

        J.HilkJ 1 Reply Last reply
        1
        • JonBJ JonB

          @J-Hilk
          And why C++ allows you to have a different definition from declaration for this case is beyond me....

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #8

          @JonB This is allowed because const is purely an implementation detail when passing by value


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          0
          • JonBJ JonB has marked this topic as solved on
          • JonBJ JonB

            Over in https://forum.qt.io/topic/146160/unresolved-external-symbol-error OP declared:

            template<typename T>
            bool Numbers::isPerfectPower(const T& number, const int &n)
            

            and then proceeds to instantiate it with T as e.g. double.

            On the basis of the C++ mantra of "why write 1 token when you can write 3", is it now the C++ "thing" that we pass numbers as const type & when we could write plain type? I would have written

            template<typename T>
            bool Numbers::isPerfectPower(T number, int n)
            

            For the T unless it's some "complex numeric type", such as perhaps an imaginary or unlimited precision number, why should I prefer const T & over T here? And certainly as for the second argument, why const int & over int?

            Is this just the modern C++ style? Is there some reason why it's more suitable here perhaps in a template? In general do you pass ints as const int &? Or do people just like typing a lot?

            Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #9

            There's nothing "technically" wrong here. The problem here is bad API design. On one hand it tries to be generic, so it doesn't restrict the type and uses const& for cases where you pass some "big" type that benefits from passing by reference. On the other it pessimizes the actually intended use case, which are the basic numeric types. So basically it's the worst of both worlds. It's optimized for case it won't be used for.
            A good API design would first analyze use cases. If it's just for the basic types you can restrict the allowed types with something like std::is_arithmetic or a concept and pass by value. If it's for any type, but you don't want to loose on performance for any case then provide an overload for the two ways.

            Christian EhrlicherC 1 Reply Last reply
            3
            • Chris KawaC Chris Kawa

              There's nothing "technically" wrong here. The problem here is bad API design. On one hand it tries to be generic, so it doesn't restrict the type and uses const& for cases where you pass some "big" type that benefits from passing by reference. On the other it pessimizes the actually intended use case, which are the basic numeric types. So basically it's the worst of both worlds. It's optimized for case it won't be used for.
              A good API design would first analyze use cases. If it's just for the basic types you can restrict the allowed types with something like std::is_arithmetic or a concept and pass by value. If it's for any type, but you don't want to loose on performance for any case then provide an overload for the two ways.

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #10

              What's wrong with

              template <typename T>
              bool Numbers::isPerfectPower(T &&number, int n);
              

              :)

              https://godbolt.org/z/afW38b9e8

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              Chris KawaC 1 Reply Last reply
              1
              • Christian EhrlicherC Christian Ehrlicher

                What's wrong with

                template <typename T>
                bool Numbers::isPerfectPower(T &&number, int n);
                

                :)

                https://godbolt.org/z/afW38b9e8

                Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #11

                @Christian-Ehrlicher said:

                What's wrong with

                This:
                https://godbolt.org/z/bxcs7b355

                kshegunovK 1 Reply Last reply
                1
                • JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by
                  #12

                  God I love this --- an assembly language debate! :D

                  J.HilkJ 1 Reply Last reply
                  0
                  • JonBJ JonB

                    God I love this --- an assembly language debate! :D

                    J.HilkJ Offline
                    J.HilkJ Offline
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #13

                    @JonB said in Unnecessary const referencing:

                    God I love this --- an assembly language debate! :D

                    alt text


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      @Christian-Ehrlicher said:

                      What's wrong with

                      This:
                      https://godbolt.org/z/bxcs7b355

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #14

                      @Chris-Kawa said in Unnecessary const referencing:

                      @Christian-Ehrlicher said:

                      What's wrong with

                      This:
                      https://godbolt.org/z/bxcs7b355

                      Of course one would do something like this, instead:

                      template <typename T>
                      std::remove_reference_t<T> foo1(T&& a) { return std::forward<T>(a) + 42; }
                      

                      https://godbolt.org/z/8nT5verW4

                      Granted, it still misses the opportunity to use lea instead of resolving the address through mov but works with whatever you pass it. I'd argue that for numeric/primitive types the compiler should expand a const lvalue to a copy at the optimizer pass, but it apparently doesn't.

                      Read and abide by the Qt Code of Conduct

                      JonBJ Chris KawaC 2 Replies Last reply
                      0
                      • kshegunovK kshegunov

                        @Chris-Kawa said in Unnecessary const referencing:

                        @Christian-Ehrlicher said:

                        What's wrong with

                        This:
                        https://godbolt.org/z/bxcs7b355

                        Of course one would do something like this, instead:

                        template <typename T>
                        std::remove_reference_t<T> foo1(T&& a) { return std::forward<T>(a) + 42; }
                        

                        https://godbolt.org/z/8nT5verW4

                        Granted, it still misses the opportunity to use lea instead of resolving the address through mov but works with whatever you pass it. I'd argue that for numeric/primitive types the compiler should expand a const lvalue to a copy at the optimizer pass, but it apparently doesn't.

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #15

                        @kshegunov
                        Why write this getting-more-complex-all-the-time code if you can instead write:

                        template <typename T>
                        bool Numbers::isPerfectPower(T number, int n);
                        

                        (given usage for POD numerics)? I just don't get how having to know about and add in

                        std::remove_reference_t<T>
                        std::forward<T>
                        

                        is anything other than making C++ harder. I like C++, but what you're asking me, the programmer, to remember is getting out of hand.....

                        Chris KawaC 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @kshegunov
                          Why write this getting-more-complex-all-the-time code if you can instead write:

                          template <typename T>
                          bool Numbers::isPerfectPower(T number, int n);
                          

                          (given usage for POD numerics)? I just don't get how having to know about and add in

                          std::remove_reference_t<T>
                          std::forward<T>
                          

                          is anything other than making C++ harder. I like C++, but what you're asking me, the programmer, to remember is getting out of hand.....

                          Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by Chris Kawa
                          #16

                          @JonB said:

                          Why write this getting-more-complex-all-the-time code if you can instead write

                          Because nothing in that syntax prevents you from passing e.g. a BigNum class instance, that would be heavily penalized for using a by value parameter (copy).

                          That's why I mentioned restricting possible inputs e.g.

                          template<typename T>
                          concept ByValueType = std::is_arithmetic_v<T>;
                          
                          template <ByValueType T>
                          bool Numbers::isPerfectPower(T number, int n);
                          

                          or whatever other condition you think is appropriate, like checking the sizeof of the type to see if it fits in a register or using some custom type traits to separate types that should be passed by value from those that benefit from referencing.

                          Of course all of this discussion is academic given how wasteful the actual implementation of the OPs function is. Any benefits we come up on the parameter front are immediately buried just few lines into the function body, but hey, why not :)

                          1 Reply Last reply
                          1
                          • kshegunovK kshegunov

                            @Chris-Kawa said in Unnecessary const referencing:

                            @Christian-Ehrlicher said:

                            What's wrong with

                            This:
                            https://godbolt.org/z/bxcs7b355

                            Of course one would do something like this, instead:

                            template <typename T>
                            std::remove_reference_t<T> foo1(T&& a) { return std::forward<T>(a) + 42; }
                            

                            https://godbolt.org/z/8nT5verW4

                            Granted, it still misses the opportunity to use lea instead of resolving the address through mov but works with whatever you pass it. I'd argue that for numeric/primitive types the compiler should expand a const lvalue to a copy at the optimizer pass, but it apparently doesn't.

                            Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by Chris Kawa
                            #17

                            @kshegunov Sure, but that's kinda another topic. What you show is just the intended benefit of small perfectly forwarded functions i.e. they completely disappear via inlining. That wouldn't happen though in a longer function, like what the OP has, so the benefit you show is indeed valid, but not really related to the topic at hand. Notice that you're actually doing what I proposed i.e. have an overload for copy and ref variants. The inlined && forward is just an unrelated complication for style points.

                            Btw. I love how the float version transforms into a fixed point xmm arithmetic with magic constant. Compilers are so smart these days :)

                            kshegunovK 1 Reply Last reply
                            0
                            • Chris KawaC Chris Kawa

                              @kshegunov Sure, but that's kinda another topic. What you show is just the intended benefit of small perfectly forwarded functions i.e. they completely disappear via inlining. That wouldn't happen though in a longer function, like what the OP has, so the benefit you show is indeed valid, but not really related to the topic at hand. Notice that you're actually doing what I proposed i.e. have an overload for copy and ref variants. The inlined && forward is just an unrelated complication for style points.

                              Btw. I love how the float version transforms into a fixed point xmm arithmetic with magic constant. Compilers are so smart these days :)

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by kshegunov
                              #18

                              @Chris-Kawa said in Unnecessary const referencing:

                              Notice that you're actually doing what I proposed i.e. have an overload for copy and ref variants.

                              No argument there.

                              The inlined && forward is just an unrelated complication for style points.

                              As far as we are talking + 42, if for example the body was something like:

                              template <typename T>
                              std::remove_reference_t<T> foo1(T&& a) {
                                  return smthng(std::forward<T>(a)) + 42;
                              }
                              

                              Where smthng is some other templated nonsense (or simply overloaded), then, I'm sure you'd agree the forward is no longer redundant. :)

                              Btw. I love how the float version transforms into a fixed point xmm arithmetic with magic constant. Compilers are so smart these days :)

                              Yeah, true enough. Although you can still catch them missing optimization opportunities from time to time.

                              @JonB said in Unnecessary const referencing:

                              Why write this getting-more-complex-all-the-time code if you can ...

                              What Chris said (... and since this is indeed an academic discussion at this point).

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0

                              • Login

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