Calling a method with an array of pointers to class::method












0















I want to call a method that will accept as an argument a pointer to a list of class:method pointers:



void dispatch ( int cmdCount, methodFunction *pointer  ) {
...
}


This typedef creates methodFunction:



typedef void ( ClassName::*methodFunction )( char, char );


But I cannot see how to make ClassName something that gets passed to dispatch. I think this needs some form of template, but I am not clear on templates yet.



Here is my entire code (drop code into TemplateTest.ino and code.h:



    //  Template Test
#include "code.h"

Dispatcher *dispatcher;
Example1 ex1;
Example2 ex2;

void setup() {
Serial.begin ( 115200 );

ex1.execute ( 'a', '+' );
ex1.execute ( 'b', '-' );
ex2.execute ( 'y', '?' );
}

void loop() {}

<<<<<<<<<< NEW FILE: code.h >>>>>>>>>>>>

#pragma once

class Dispatcher {
public:
template<class T>

void dispatch ( T& instance, void(T::*func)(char sel, char act), char def [2], int cmdCount ) {
// Walk through the array containing sel,act pairs.
// When we find a match, launch the function from
// tPointer with the same index value.
for (int i = 0; i < cmdCount; i++) {
char _sel = def [i] [0];
char _act = def [i] [1];
if (( sel == _sel ) && ( act == _act )) {
( *T [i] )( sel, act );
return;
}
}
}
};

// Example 1 Code
char ex1Array [2] = {
{'a','+'},
{'a','-'},
{'b','+'},
{'b','-'},
};

class Example1 {
public:

char *_name = "Template Example 1";

Dispatcher disp;

static const int cmdCount = sizeof ( ex1Array ) / sizeof ( ex1Array [0] );

typedef void ( Example1::*FunctionPointer )( char sel, char act );

// Function dispatch table
FunctionPointer cmdMethods [cmdCount] = {
&Example1::alphaPlus,
&Example1::alphaMinus,
&Example1::betaPlus,
&Example1::betaMinus,
};

Example1 () {
}

void alphaPlus ( char sel, char act ) {
Serial.println ( F ( "Alpha +" ) );
}
void alphaMinus ( char sel, char act ) {
Serial.println ( F ( "Alpha -" ) );
}
void betaPlus ( char sel, char act ) {
Serial.println ( F ( "Beta +" ) );
}
void betaMinus ( char sel, char act ) {
Serial.println ( F ( "Beta -" ) );
}

void execute ( char sel, char act ) {
disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex1Array[0], cmdCount );
}

};

// Example 2
char ex2Array [2] = {
{'x','?'},
{'y','?'},
{'z','?'},
};

class Example2 {
public:

char *_name = "Template Example 2";

Dispatcher disp;

static const int cmdCount = sizeof ( ex2Array ) / sizeof ( ex2Array [0] );

typedef void ( Example2::*FunctionPointer )( char sel, char act );

// Function dispatch table
FunctionPointer cmdMethods [cmdCount] = {
&Example2::x,
&Example2::y,
&Example2::z,
};

Example2 () {
}

void x ( char sel, char act ) {
Serial.println ( F ( "X" ) );
}
void y ( char sel, char act ) {
Serial.println ( F ( "Y" ) );
}
void z ( char sel, char act ) {
Serial.println ( F ( "Z" ) );
}

void execute ( char sel, char act ) {
disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex2Array [0], cmdCount );
}
};









share|improve this question





























    0















    I want to call a method that will accept as an argument a pointer to a list of class:method pointers:



    void dispatch ( int cmdCount, methodFunction *pointer  ) {
    ...
    }


    This typedef creates methodFunction:



    typedef void ( ClassName::*methodFunction )( char, char );


    But I cannot see how to make ClassName something that gets passed to dispatch. I think this needs some form of template, but I am not clear on templates yet.



    Here is my entire code (drop code into TemplateTest.ino and code.h:



        //  Template Test
    #include "code.h"

    Dispatcher *dispatcher;
    Example1 ex1;
    Example2 ex2;

    void setup() {
    Serial.begin ( 115200 );

    ex1.execute ( 'a', '+' );
    ex1.execute ( 'b', '-' );
    ex2.execute ( 'y', '?' );
    }

    void loop() {}

    <<<<<<<<<< NEW FILE: code.h >>>>>>>>>>>>

    #pragma once

    class Dispatcher {
    public:
    template<class T>

    void dispatch ( T& instance, void(T::*func)(char sel, char act), char def [2], int cmdCount ) {
    // Walk through the array containing sel,act pairs.
    // When we find a match, launch the function from
    // tPointer with the same index value.
    for (int i = 0; i < cmdCount; i++) {
    char _sel = def [i] [0];
    char _act = def [i] [1];
    if (( sel == _sel ) && ( act == _act )) {
    ( *T [i] )( sel, act );
    return;
    }
    }
    }
    };

    // Example 1 Code
    char ex1Array [2] = {
    {'a','+'},
    {'a','-'},
    {'b','+'},
    {'b','-'},
    };

    class Example1 {
    public:

    char *_name = "Template Example 1";

    Dispatcher disp;

    static const int cmdCount = sizeof ( ex1Array ) / sizeof ( ex1Array [0] );

    typedef void ( Example1::*FunctionPointer )( char sel, char act );

    // Function dispatch table
    FunctionPointer cmdMethods [cmdCount] = {
    &Example1::alphaPlus,
    &Example1::alphaMinus,
    &Example1::betaPlus,
    &Example1::betaMinus,
    };

    Example1 () {
    }

    void alphaPlus ( char sel, char act ) {
    Serial.println ( F ( "Alpha +" ) );
    }
    void alphaMinus ( char sel, char act ) {
    Serial.println ( F ( "Alpha -" ) );
    }
    void betaPlus ( char sel, char act ) {
    Serial.println ( F ( "Beta +" ) );
    }
    void betaMinus ( char sel, char act ) {
    Serial.println ( F ( "Beta -" ) );
    }

    void execute ( char sel, char act ) {
    disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex1Array[0], cmdCount );
    }

    };

    // Example 2
    char ex2Array [2] = {
    {'x','?'},
    {'y','?'},
    {'z','?'},
    };

    class Example2 {
    public:

    char *_name = "Template Example 2";

    Dispatcher disp;

    static const int cmdCount = sizeof ( ex2Array ) / sizeof ( ex2Array [0] );

    typedef void ( Example2::*FunctionPointer )( char sel, char act );

    // Function dispatch table
    FunctionPointer cmdMethods [cmdCount] = {
    &Example2::x,
    &Example2::y,
    &Example2::z,
    };

    Example2 () {
    }

    void x ( char sel, char act ) {
    Serial.println ( F ( "X" ) );
    }
    void y ( char sel, char act ) {
    Serial.println ( F ( "Y" ) );
    }
    void z ( char sel, char act ) {
    Serial.println ( F ( "Z" ) );
    }

    void execute ( char sel, char act ) {
    disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex2Array [0], cmdCount );
    }
    };









    share|improve this question



























      0












      0








      0








      I want to call a method that will accept as an argument a pointer to a list of class:method pointers:



      void dispatch ( int cmdCount, methodFunction *pointer  ) {
      ...
      }


      This typedef creates methodFunction:



      typedef void ( ClassName::*methodFunction )( char, char );


      But I cannot see how to make ClassName something that gets passed to dispatch. I think this needs some form of template, but I am not clear on templates yet.



      Here is my entire code (drop code into TemplateTest.ino and code.h:



          //  Template Test
      #include "code.h"

      Dispatcher *dispatcher;
      Example1 ex1;
      Example2 ex2;

      void setup() {
      Serial.begin ( 115200 );

      ex1.execute ( 'a', '+' );
      ex1.execute ( 'b', '-' );
      ex2.execute ( 'y', '?' );
      }

      void loop() {}

      <<<<<<<<<< NEW FILE: code.h >>>>>>>>>>>>

      #pragma once

      class Dispatcher {
      public:
      template<class T>

      void dispatch ( T& instance, void(T::*func)(char sel, char act), char def [2], int cmdCount ) {
      // Walk through the array containing sel,act pairs.
      // When we find a match, launch the function from
      // tPointer with the same index value.
      for (int i = 0; i < cmdCount; i++) {
      char _sel = def [i] [0];
      char _act = def [i] [1];
      if (( sel == _sel ) && ( act == _act )) {
      ( *T [i] )( sel, act );
      return;
      }
      }
      }
      };

      // Example 1 Code
      char ex1Array [2] = {
      {'a','+'},
      {'a','-'},
      {'b','+'},
      {'b','-'},
      };

      class Example1 {
      public:

      char *_name = "Template Example 1";

      Dispatcher disp;

      static const int cmdCount = sizeof ( ex1Array ) / sizeof ( ex1Array [0] );

      typedef void ( Example1::*FunctionPointer )( char sel, char act );

      // Function dispatch table
      FunctionPointer cmdMethods [cmdCount] = {
      &Example1::alphaPlus,
      &Example1::alphaMinus,
      &Example1::betaPlus,
      &Example1::betaMinus,
      };

      Example1 () {
      }

      void alphaPlus ( char sel, char act ) {
      Serial.println ( F ( "Alpha +" ) );
      }
      void alphaMinus ( char sel, char act ) {
      Serial.println ( F ( "Alpha -" ) );
      }
      void betaPlus ( char sel, char act ) {
      Serial.println ( F ( "Beta +" ) );
      }
      void betaMinus ( char sel, char act ) {
      Serial.println ( F ( "Beta -" ) );
      }

      void execute ( char sel, char act ) {
      disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex1Array[0], cmdCount );
      }

      };

      // Example 2
      char ex2Array [2] = {
      {'x','?'},
      {'y','?'},
      {'z','?'},
      };

      class Example2 {
      public:

      char *_name = "Template Example 2";

      Dispatcher disp;

      static const int cmdCount = sizeof ( ex2Array ) / sizeof ( ex2Array [0] );

      typedef void ( Example2::*FunctionPointer )( char sel, char act );

      // Function dispatch table
      FunctionPointer cmdMethods [cmdCount] = {
      &Example2::x,
      &Example2::y,
      &Example2::z,
      };

      Example2 () {
      }

      void x ( char sel, char act ) {
      Serial.println ( F ( "X" ) );
      }
      void y ( char sel, char act ) {
      Serial.println ( F ( "Y" ) );
      }
      void z ( char sel, char act ) {
      Serial.println ( F ( "Z" ) );
      }

      void execute ( char sel, char act ) {
      disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex2Array [0], cmdCount );
      }
      };









      share|improve this question
















      I want to call a method that will accept as an argument a pointer to a list of class:method pointers:



      void dispatch ( int cmdCount, methodFunction *pointer  ) {
      ...
      }


      This typedef creates methodFunction:



      typedef void ( ClassName::*methodFunction )( char, char );


      But I cannot see how to make ClassName something that gets passed to dispatch. I think this needs some form of template, but I am not clear on templates yet.



      Here is my entire code (drop code into TemplateTest.ino and code.h:



          //  Template Test
      #include "code.h"

      Dispatcher *dispatcher;
      Example1 ex1;
      Example2 ex2;

      void setup() {
      Serial.begin ( 115200 );

      ex1.execute ( 'a', '+' );
      ex1.execute ( 'b', '-' );
      ex2.execute ( 'y', '?' );
      }

      void loop() {}

      <<<<<<<<<< NEW FILE: code.h >>>>>>>>>>>>

      #pragma once

      class Dispatcher {
      public:
      template<class T>

      void dispatch ( T& instance, void(T::*func)(char sel, char act), char def [2], int cmdCount ) {
      // Walk through the array containing sel,act pairs.
      // When we find a match, launch the function from
      // tPointer with the same index value.
      for (int i = 0; i < cmdCount; i++) {
      char _sel = def [i] [0];
      char _act = def [i] [1];
      if (( sel == _sel ) && ( act == _act )) {
      ( *T [i] )( sel, act );
      return;
      }
      }
      }
      };

      // Example 1 Code
      char ex1Array [2] = {
      {'a','+'},
      {'a','-'},
      {'b','+'},
      {'b','-'},
      };

      class Example1 {
      public:

      char *_name = "Template Example 1";

      Dispatcher disp;

      static const int cmdCount = sizeof ( ex1Array ) / sizeof ( ex1Array [0] );

      typedef void ( Example1::*FunctionPointer )( char sel, char act );

      // Function dispatch table
      FunctionPointer cmdMethods [cmdCount] = {
      &Example1::alphaPlus,
      &Example1::alphaMinus,
      &Example1::betaPlus,
      &Example1::betaMinus,
      };

      Example1 () {
      }

      void alphaPlus ( char sel, char act ) {
      Serial.println ( F ( "Alpha +" ) );
      }
      void alphaMinus ( char sel, char act ) {
      Serial.println ( F ( "Alpha -" ) );
      }
      void betaPlus ( char sel, char act ) {
      Serial.println ( F ( "Beta +" ) );
      }
      void betaMinus ( char sel, char act ) {
      Serial.println ( F ( "Beta -" ) );
      }

      void execute ( char sel, char act ) {
      disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex1Array[0], cmdCount );
      }

      };

      // Example 2
      char ex2Array [2] = {
      {'x','?'},
      {'y','?'},
      {'z','?'},
      };

      class Example2 {
      public:

      char *_name = "Template Example 2";

      Dispatcher disp;

      static const int cmdCount = sizeof ( ex2Array ) / sizeof ( ex2Array [0] );

      typedef void ( Example2::*FunctionPointer )( char sel, char act );

      // Function dispatch table
      FunctionPointer cmdMethods [cmdCount] = {
      &Example2::x,
      &Example2::y,
      &Example2::z,
      };

      Example2 () {
      }

      void x ( char sel, char act ) {
      Serial.println ( F ( "X" ) );
      }
      void y ( char sel, char act ) {
      Serial.println ( F ( "Y" ) );
      }
      void z ( char sel, char act ) {
      Serial.println ( F ( "Z" ) );
      }

      void execute ( char sel, char act ) {
      disp.dispatch ( *this, cmdMethods [0], 'a', 'b', ex2Array [0], cmdCount );
      }
      };






      c++ templates arduino typedef






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 7:55







      Bob Jones

















      asked Nov 20 '18 at 3:22









      Bob JonesBob Jones

      1,08152452




      1,08152452
























          1 Answer
          1






          active

          oldest

          votes


















          0














          dispatch should called with an instance.



          template<class T>
          void dispatch(T& instance, void(T::*func)(char, char), char param1, char param2 )
          {
          instance.*func(param1, param2);
          }


          call dispatch:



          dispatch(*this, cmdMethods[0], 'a', 'b');





          share|improve this answer
























          • Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

            – Bob Jones
            Nov 20 '18 at 6:42











          • @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

            – KIIV
            Nov 20 '18 at 11:18











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385750%2fcalling-a-method-with-an-array-of-pointers-to-classmethod%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          dispatch should called with an instance.



          template<class T>
          void dispatch(T& instance, void(T::*func)(char, char), char param1, char param2 )
          {
          instance.*func(param1, param2);
          }


          call dispatch:



          dispatch(*this, cmdMethods[0], 'a', 'b');





          share|improve this answer
























          • Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

            – Bob Jones
            Nov 20 '18 at 6:42











          • @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

            – KIIV
            Nov 20 '18 at 11:18
















          0














          dispatch should called with an instance.



          template<class T>
          void dispatch(T& instance, void(T::*func)(char, char), char param1, char param2 )
          {
          instance.*func(param1, param2);
          }


          call dispatch:



          dispatch(*this, cmdMethods[0], 'a', 'b');





          share|improve this answer
























          • Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

            – Bob Jones
            Nov 20 '18 at 6:42











          • @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

            – KIIV
            Nov 20 '18 at 11:18














          0












          0








          0







          dispatch should called with an instance.



          template<class T>
          void dispatch(T& instance, void(T::*func)(char, char), char param1, char param2 )
          {
          instance.*func(param1, param2);
          }


          call dispatch:



          dispatch(*this, cmdMethods[0], 'a', 'b');





          share|improve this answer













          dispatch should called with an instance.



          template<class T>
          void dispatch(T& instance, void(T::*func)(char, char), char param1, char param2 )
          {
          instance.*func(param1, param2);
          }


          call dispatch:



          dispatch(*this, cmdMethods[0], 'a', 'b');






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 '18 at 3:47









          AIMIN PANAIMIN PAN

          22928




          22928













          • Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

            – Bob Jones
            Nov 20 '18 at 6:42











          • @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

            – KIIV
            Nov 20 '18 at 11:18



















          • Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

            – Bob Jones
            Nov 20 '18 at 6:42











          • @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

            – KIIV
            Nov 20 '18 at 11:18

















          Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

          – Bob Jones
          Nov 20 '18 at 6:42





          Thanks, AIMIN PAN. Your input helped. I have updated the posted code with your suggestions but there are still five compile errors.

          – Bob Jones
          Nov 20 '18 at 6:42













          @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

          – KIIV
          Nov 20 '18 at 11:18





          @BobJones For example you can't use sel and act from void(T::*func)(char sel, char act). How would you even pass it? The only variable you have is the func. Another error is about passing too many arguments to the dispatch (maybe related with previous).

          – KIIV
          Nov 20 '18 at 11:18




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385750%2fcalling-a-method-with-an-array-of-pointers-to-classmethod%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Guess what letter conforming each word

          Port of Spain

          Run scheduled task as local user group (not BUILTIN)