Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. What are some stupid-useful coding tricks you rely on?

What are some stupid-useful coding tricks you rely on?

Scheduled Pinned Locked Moved The Lounge
hardwareiotquestionworkspace
36 Posts 15 Posters 0 Views 1 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.
  • H honey the codewitch

    I was just thinking about this today when I was retooling my IoT button library. I use template-instance statics to get around not being able to pass an argument to an interrupt routine (which must be void ()) under the Arduino framework

    template
    class button {
    // assign this to "this" on initialization of a class instance
    static button* m_this;
    // ISR
    static IRAM_ATTR void isr() { m_this->... }
    };
    ...

    like that. It's really useful but it makes me kinda wanna puke too, even though there's absolutely nothing wrong with it, technically speaking, since it doesn't make sense to have two buttons on one pin anyway, and you're not dealing in a pre-emptively threaded environment in 80% of all cases on 80% of all platforms. Template-instance statics (i don't know what else to call them) are something I have to rely on way more than I wish I had to, but I am glad they are there. What's your go to coding technique that nevertheless makes you uncomfortable?

    To err is human. Fortune favors the monsters.

    Mircea NeacsuM Offline
    Mircea NeacsuM Offline
    Mircea Neacsu
    wrote on last edited by
    #20

    Maybe the "Named parameter idiom"[^]. Instead of:

    Rectangle r(10, 15, 24, 42);

    you can write:

    Rectangle r;
    r.left(10).top(15).width(24).height(42);

    Makes a world of difference when you have complicated objects with lots of parameters.

    Mircea

    H C 2 Replies Last reply
    0
    • G Gary R Wheeler

      honey the codewitch wrote:

      Template-instance statics

      I've done that for cases where I didn't want to pass around a singleton instance:

      class API
      {
      public:

      static void DoThing();
      

      private:

      API();
      
      static API \*\_This;
      

      };

      API *API::_This = NULL;

      void API::DoThing()
      {
      if (_This == NULL) _This = new API();
      }

      It's useful for create-only-if-needed scenarios. For us, those arise fairly often adapting to different hardware. They're also useful when the creation process is expensive or time-consuming. In C++ I like the idea that API::DoThing() is a blatant syntax for a singleton concept. I've also had cases where the public static functions define the 'API' for a collection, while the instance members and values are the elements in the collection. Now, I know that singletons are a 'code smell', but trust me... I know what I'm doing. :-D

      Software Zen: delete this;

      H Offline
      H Offline
      honey the codewitch
      wrote on last edited by
      #21

      I totally get what you're saying. Just for clarity though template-instance statics add another dimension to statics because they are not shared between different instantiations of the same template.

      template struct foo final {
      static int value;
      };
      ...

      ...
      foo<1>::value = 5;
      foo<2>::value = 4;
      printf("%d + %d = %d\n",foo<1>::value,foo<2>::value,foo<1>::value+foo<2>::value);
      // prints 5 + 4 = 9

      To err is human. Fortune favors the monsters.

      G 1 Reply Last reply
      0
      • Mircea NeacsuM Mircea Neacsu

        Maybe the "Named parameter idiom"[^]. Instead of:

        Rectangle r(10, 15, 24, 42);

        you can write:

        Rectangle r;
        r.left(10).top(15).width(24).height(42);

        Makes a world of difference when you have complicated objects with lots of parameters.

        Mircea

        H Offline
        H Offline
        honey the codewitch
        wrote on last edited by
        #22

        yikes! I've done similar, but mostly for constructing Abstract Syntax Trees.

        To err is human. Fortune favors the monsters.

        1 Reply Last reply
        0
        • R raddevus

          CPallini wrote:

          You could do that with a virtual function, couldn't you?

          I'm not sure. What is a virtual function? Can you create a virtual function in Arduino code? I've been developing software for 30 years and I remember something about vtables and maybe a virtual function is a function lookup? I'm just guessing to see how close I am to your answer. let me know, thanks. :) Oh, base-class abstract method? yes, could be done. 6 one way, half a dozen the other. :laugh: C# has delegates. This whole, "call some function I define in the future" is really done in many different ways with various names. :-D

          H Offline
          H Offline
          honey the codewitch
          wrote on last edited by
          #23

          A virtual function is a function that can be overloaded by a derived class. In C# you mark such a function as virtual, IIRC - same as you do in C++.

          To err is human. Fortune favors the monsters.

          1 Reply Last reply
          0
          • R raddevus

            I had a number of buttons on my Arduino project that needed to do similar (but slightly different) things. I had all this code to handle the button debouncing. So then I discovered a nice way to pass a pointer to a function (button press handler) so that the code was the same no matter which button was pressed, but the specific function for the correct button is called. And, all the debouncing for each button is wrapped up nicely.

            typedef void (*ButtonPressHandler) (void);

            void checkButton(const int BUTTON, bool &last, bool &current, ButtonPressHandler handler ){
            current = debounce(last, BUTTON); // Read debounced state
            if (last == LOW && current == HIGH) // If it was pressed…
            {
            // This runs the code that we want to happen
            // when the user presses the button. The function ptr
            // allows us to do different types of work
            handler();
            }
            last = current; // Reset button value
            }

            boolean debounce(boolean last, int button)
            {
            boolean current = digitalRead(button); // Read the button state
            if (last != current) // If it's different…
            {
            delay(5); // Wait 5ms
            current = digitalRead(button); // Read it again
            }
            return current; // Return the current value
            }

            Now you just call it with whichever button is pressed so it can all be handled:

            // My device has a button that changes the room (location)
            // The last argument is the button handler code (pointer to function)
            checkButton(ROOM_BTN,roomBtnPrev,roomBtnCurrent,checkChangeRoomButton);

            // It also has a button that turns data writing (to SD Card) on / off
            checkButton(DATA_BTN, dataBtnPrev, dataBtnCurrent, checkWriteDataButton);

            Now they are both handled the same way and all the debouncing is wrapped up. What do you think?

            J Offline
            J Offline
            jmaida
            wrote on last edited by
            #24

            Viewing this as a old C programmer, it all makes sense, is quite clear and does the job. C++ version seems to introduce fuzziness and obfuscation (although straight C can do the same thing). Cute or clever does not always = maintainable code. Just saying.

            "A little time, a little trouble, your better day" Badfinger

            1 Reply Last reply
            0
            • Mircea NeacsuM Mircea Neacsu

              Maybe the "Named parameter idiom"[^]. Instead of:

              Rectangle r(10, 15, 24, 42);

              you can write:

              Rectangle r;
              r.left(10).top(15).width(24).height(42);

              Makes a world of difference when you have complicated objects with lots of parameters.

              Mircea

              C Offline
              C Offline
              CPallini
              wrote on last edited by
              #25

              Nice. With C++ 20, you might enjoy designated initializers[^].

              "In testa che avete, Signor di Ceprano?" -- Rigoletto

              1 Reply Last reply
              0
              • R raddevus

                I had a number of buttons on my Arduino project that needed to do similar (but slightly different) things. I had all this code to handle the button debouncing. So then I discovered a nice way to pass a pointer to a function (button press handler) so that the code was the same no matter which button was pressed, but the specific function for the correct button is called. And, all the debouncing for each button is wrapped up nicely.

                typedef void (*ButtonPressHandler) (void);

                void checkButton(const int BUTTON, bool &last, bool &current, ButtonPressHandler handler ){
                current = debounce(last, BUTTON); // Read debounced state
                if (last == LOW && current == HIGH) // If it was pressed…
                {
                // This runs the code that we want to happen
                // when the user presses the button. The function ptr
                // allows us to do different types of work
                handler();
                }
                last = current; // Reset button value
                }

                boolean debounce(boolean last, int button)
                {
                boolean current = digitalRead(button); // Read the button state
                if (last != current) // If it's different…
                {
                delay(5); // Wait 5ms
                current = digitalRead(button); // Read it again
                }
                return current; // Return the current value
                }

                Now you just call it with whichever button is pressed so it can all be handled:

                // My device has a button that changes the room (location)
                // The last argument is the button handler code (pointer to function)
                checkButton(ROOM_BTN,roomBtnPrev,roomBtnCurrent,checkChangeRoomButton);

                // It also has a button that turns data writing (to SD Card) on / off
                checkButton(DATA_BTN, dataBtnPrev, dataBtnCurrent, checkWriteDataButton);

                Now they are both handled the same way and all the debouncing is wrapped up. What do you think?

                B Offline
                B Offline
                BillWoodruff
                wrote on last edited by
                #26

                raddevus wrote:

                What do you think?

                I think this "belongs" on one of the technical forums ... but, given the general neglect of many forums, and the free-for-all the Lounge has become, I am just "blowing smoke" :wtf: :)

                «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                Mircea NeacsuM 1 Reply Last reply
                0
                • H honey the codewitch

                  I totally get what you're saying. Just for clarity though template-instance statics add another dimension to statics because they are not shared between different instantiations of the same template.

                  template struct foo final {
                  static int value;
                  };
                  ...

                  ...
                  foo<1>::value = 5;
                  foo<2>::value = 4;
                  printf("%d + %d = %d\n",foo<1>::value,foo<2>::value,foo<1>::value+foo<2>::value);
                  // prints 5 + 4 = 9

                  To err is human. Fortune favors the monsters.

                  G Offline
                  G Offline
                  Gary Wheeler
                  wrote on last edited by
                  #27

                  Congratulations, your Witch-ness! You have successfully taught an Old Dog a wonderful new trick! :-\

                  Software Zen: delete this;

                  H 1 Reply Last reply
                  0
                  • G Gary Wheeler

                    Congratulations, your Witch-ness! You have successfully taught an Old Dog a wonderful new trick! :-\

                    Software Zen: delete this;

                    H Offline
                    H Offline
                    honey the codewitch
                    wrote on last edited by
                    #28

                    I didn't tell you the downside. You must initialize the statics to avoid a linker error, and I don't know about C++20 but previous versions require declarations like this for statics:

                    template
                    int_button*
                    int_button::m_this = nullptr;

                    To err is human. Fortune favors the monsters.

                    G 1 Reply Last reply
                    0
                    • H honey the codewitch

                      I didn't tell you the downside. You must initialize the statics to avoid a linker error, and I don't know about C++20 but previous versions require declarations like this for statics:

                      template
                      int_button*
                      int_button::m_this = nullptr;

                      To err is human. Fortune favors the monsters.

                      G Offline
                      G Offline
                      Gary Wheeler
                      wrote on last edited by
                      #29

                      I don't think that's a downside, really. I'd expect that to be required initialization, since non-template static members require it.

                      Software Zen: delete this;

                      H 1 Reply Last reply
                      0
                      • G Gary Wheeler

                        I don't think that's a downside, really. I'd expect that to be required initialization, since non-template static members require it.

                        Software Zen: delete this;

                        H Offline
                        H Offline
                        honey the codewitch
                        wrote on last edited by
                        #30

                        I'm referring to the nasty syntax required. :)

                        To err is human. Fortune favors the monsters.

                        1 Reply Last reply
                        0
                        • R raddevus

                          Thanks, that was very nice and I accept your apology. I will take a look at the post. I honestly was offering the original code just as an interesting thing. I was probably triggered by your post because I started out in IT back in '91 and since then it has always been a "my code is better than yours" pissing war with Devs. :laugh: I started out in Tech Support and knew I was a slug in the IT world. Worked my way into QA and was there for 5 years or so and remember when this Dilbert came out[^]. Oh, it's funny now. I finally made worked my way into Dev and have been here for about 22 years but I find that Devs are (and have always been) so competitive and are "always right". it just kind of triggers me. When I was in QA if a dev ticked me off, I would just test his code, find a critical bug and then post it Friday afternoon. :laugh:

                          M Offline
                          M Offline
                          Marcelo Huerta
                          wrote on last edited by
                          #31

                          raddevus wrote:

                          When I was in QA if a dev ticked me off, I would just test his code, find a critical bug and then post it Friday afternoon.

                          That is evil. I love it :laugh:

                          1 Reply Last reply
                          0
                          • H honey the codewitch

                            I was just thinking about this today when I was retooling my IoT button library. I use template-instance statics to get around not being able to pass an argument to an interrupt routine (which must be void ()) under the Arduino framework

                            template
                            class button {
                            // assign this to "this" on initialization of a class instance
                            static button* m_this;
                            // ISR
                            static IRAM_ATTR void isr() { m_this->... }
                            };
                            ...

                            like that. It's really useful but it makes me kinda wanna puke too, even though there's absolutely nothing wrong with it, technically speaking, since it doesn't make sense to have two buttons on one pin anyway, and you're not dealing in a pre-emptively threaded environment in 80% of all cases on 80% of all platforms. Template-instance statics (i don't know what else to call them) are something I have to rely on way more than I wish I had to, but I am glad they are there. What's your go to coding technique that nevertheless makes you uncomfortable?

                            To err is human. Fortune favors the monsters.

                            M Offline
                            M Offline
                            Member_5893260
                            wrote on last edited by
                            #32

                            In C:

                            a^=b^=a^=b;

                            ...will swap the values of a and b by XORing them a couple of times, assuming a and b are the same size. Works for large data structures just as well as for ints: quite fast, too. Back in the days before proper video cards, this was good for swapping in entire screen contents, or faking sprites or whatever... Note that this doesn't work in C#: you have to go...:

                            a^=b;
                            b^=a;
                            a^=b;

                            ...because unlike C, C# uses the original values of the variables throughout the evaluation of the expression, so what happens if you try to run the original statement is that one variable receives the swap, but the other one is garbage. And really, it only works for ints. But it does let you swap the variables without using a third one.

                            1 Reply Last reply
                            0
                            • H honey the codewitch

                              I was just thinking about this today when I was retooling my IoT button library. I use template-instance statics to get around not being able to pass an argument to an interrupt routine (which must be void ()) under the Arduino framework

                              template
                              class button {
                              // assign this to "this" on initialization of a class instance
                              static button* m_this;
                              // ISR
                              static IRAM_ATTR void isr() { m_this->... }
                              };
                              ...

                              like that. It's really useful but it makes me kinda wanna puke too, even though there's absolutely nothing wrong with it, technically speaking, since it doesn't make sense to have two buttons on one pin anyway, and you're not dealing in a pre-emptively threaded environment in 80% of all cases on 80% of all platforms. Template-instance statics (i don't know what else to call them) are something I have to rely on way more than I wish I had to, but I am glad they are there. What's your go to coding technique that nevertheless makes you uncomfortable?

                              To err is human. Fortune favors the monsters.

                              H Offline
                              H Offline
                              HappyDotNet
                              wrote on last edited by
                              #33

                              Use Background worker report progress to trigger different conditions on the main thread. *** Ya Ya I know..background workers X| But I didn't architect the project :)

                              Private Sub Go(myList as list(of String))
                              bgw1.RunWorkerAsync(me,myList)
                              End Sub

                              Private Sub bgw1_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw1.DoWork
                              'background thread
                              Dim myList As List(Of String) = e.Argument
                              Dim listCount As Integer = myList.Count
                              'long running process
                              For i As Integer = 0 To listCount
                              Dim resultInteger = DoWork(myList(i))
                              bgw1.ReportProgress(resultInteger,myList(i))
                              Next
                              End Sub

                              Private Sub bgw1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgw1.ProgressChanged
                              'main thread
                              Dim p As Integer = e.ProgressPercentage
                              Dim s As String = CStr(e.UserState)
                              Select Case P
                              Case 1
                              lbl1.Text = s
                              Case 2
                              lbl2.Text = s
                              Case Else
                              lbl1.Text = "Invalid Result for " & s
                              lbl2.Text = "Invalid Result for " & s
                              End Select
                              End Sub

                              1 Reply Last reply
                              0
                              • B BillWoodruff

                                raddevus wrote:

                                What do you think?

                                I think this "belongs" on one of the technical forums ... but, given the general neglect of many forums, and the free-for-all the Lounge has become, I am just "blowing smoke" :wtf: :)

                                «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                                Mircea NeacsuM Offline
                                Mircea NeacsuM Offline
                                Mircea Neacsu
                                wrote on last edited by
                                #34

                                BillWoodruff wrote:

                                I am just "blowing smoke"

                                Kacey Musgraves - Blowin' Smoke - YouTube[^]

                                Mircea

                                1 Reply Last reply
                                0
                                • H honey the codewitch

                                  I was just thinking about this today when I was retooling my IoT button library. I use template-instance statics to get around not being able to pass an argument to an interrupt routine (which must be void ()) under the Arduino framework

                                  template
                                  class button {
                                  // assign this to "this" on initialization of a class instance
                                  static button* m_this;
                                  // ISR
                                  static IRAM_ATTR void isr() { m_this->... }
                                  };
                                  ...

                                  like that. It's really useful but it makes me kinda wanna puke too, even though there's absolutely nothing wrong with it, technically speaking, since it doesn't make sense to have two buttons on one pin anyway, and you're not dealing in a pre-emptively threaded environment in 80% of all cases on 80% of all platforms. Template-instance statics (i don't know what else to call them) are something I have to rely on way more than I wish I had to, but I am glad they are there. What's your go to coding technique that nevertheless makes you uncomfortable?

                                  To err is human. Fortune favors the monsters.

                                  E Offline
                                  E Offline
                                  englebart
                                  wrote on last edited by
                                  #35

                                  Always wrap any third party or sufficiently complicated built-in API with your own API. The original API or third party will change or become deprecated in about 10 years. A good rule for code that you expect to last 20 years or more. If you expect a five year life span then it might not be worth it.

                                  1 Reply Last reply
                                  0
                                  • H honey the codewitch

                                    I was just thinking about this today when I was retooling my IoT button library. I use template-instance statics to get around not being able to pass an argument to an interrupt routine (which must be void ()) under the Arduino framework

                                    template
                                    class button {
                                    // assign this to "this" on initialization of a class instance
                                    static button* m_this;
                                    // ISR
                                    static IRAM_ATTR void isr() { m_this->... }
                                    };
                                    ...

                                    like that. It's really useful but it makes me kinda wanna puke too, even though there's absolutely nothing wrong with it, technically speaking, since it doesn't make sense to have two buttons on one pin anyway, and you're not dealing in a pre-emptively threaded environment in 80% of all cases on 80% of all platforms. Template-instance statics (i don't know what else to call them) are something I have to rely on way more than I wish I had to, but I am glad they are there. What's your go to coding technique that nevertheless makes you uncomfortable?

                                    To err is human. Fortune favors the monsters.

                                    F Offline
                                    F Offline
                                    FormerBIOSGuy
                                    wrote on last edited by
                                    #36

                                    To toggle a flag variable that has values of 0 and 1: Flag = 1 - Flag

                                    FormerBIOSGuy

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups