matrix of function pointers

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Klaas Vantournhout

    #1

    matrix of function pointers

    Hi all,

    I'm in need of a matrix of function pointers, and to be honest. No
    'nice' solution has been found yet on that big big internet.

    It is possible to declare a matrix of function pointers in the following
    way

    void (*f[2][2])(int);

    But I want to know how I can declare this only using double pointers.
    like an array

    double **a;
    a = new double *[2];
    for (int i = 0; i < 2; i++)
    a[i] = new double [2];

    I would like to know this, because I have in my code something which is
    similar like below, and i want it to work. The problem is, that during
    compiling i obtain the following error.

    cannot convert 'void (* (*)[2])(int)' to 'void (***)(int)' for argument
    '1' to 'void pm_funcion(void (***)(int), int)'
    cannot convert 'void (* (*)[3])(int)' to 'void (***)(int)' for argument
    '1' to 'void pm_funcion(void (***)(int), int)'

    thanks in advance

    klaas


    //function
    void pm_function(voi d (***f) (int), int dim) {
    for (int i = 0; i < dim; i++)
    for (int j = 0; j < dim; j++)
    f[i][j](5);
    }

    int main(void) {
    void (*f[2][2])(int);
    void (*g[3][3])(int);
    // I want this to work, but it doesn not! See error above message
    pm_function(f,2 );
    pm_function(g,3 );

    }
  • benben

    #2
    Re: matrix of function pointers


    Maybe the following code would help:

    typedef void (*fnptr)(int);
    typedef fnptr** fnptr_mtrx;

    fnptr_mtrx matrix = ...

    Comment

    • John Carson

      #3
      Re: matrix of function pointers

      "Klaas Vantournhout" <no_valid_email @spam.com> wrote in message
      news:dvluqk$dcd $1@gaudi2.UGent .be[color=blue]
      > Hi all,
      >
      > I'm in need of a matrix of function pointers, and to be honest. No
      > 'nice' solution has been found yet on that big big internet.
      >
      > It is possible to declare a matrix of function pointers in the
      > following way
      >
      > void (*f[2][2])(int);
      >
      > But I want to know how I can declare this only using double pointers.
      > like an array
      >
      > double **a;
      > a = new double *[2];
      > for (int i = 0; i < 2; i++)
      > a[i] = new double [2];
      >
      > I would like to know this, because I have in my code something which
      > is similar like below, and i want it to work. The problem is, that
      > during compiling i obtain the following error.
      >
      > cannot convert 'void (* (*)[2])(int)' to 'void (***)(int)' for
      > argument '1' to 'void pm_funcion(void (***)(int), int)'
      > cannot convert 'void (* (*)[3])(int)' to 'void (***)(int)' for
      > argument '1' to 'void pm_funcion(void (***)(int), int)'
      >
      > thanks in advance
      >
      > klaas
      >
      >
      > //function
      > void pm_function(voi d (***f) (int), int dim) {
      > for (int i = 0; i < dim; i++)
      > for (int j = 0; j < dim; j++)
      > f[i][j](5);
      > }
      >
      > int main(void) {
      > void (*f[2][2])(int);
      > void (*g[3][3])(int);[/color]

      You realise of course that you have never initialised these function
      pointers to point to anything.
      [color=blue]
      > // I want this to work, but it doesn not! See error above message
      > pm_function(f,2 );
      > pm_function(g,3 );
      >
      > }[/color]

      Your problem is not specifically with function pointers. You would have the
      same problem with arrays of ints, e.g., the following won't compile for the
      same reason.

      void pm_function(int **pptr, int dim)
      {
      for (int i = 0; i < dim; i++)
      for (int j = 0; j < dim; j++)
      cout << pptr[i][j];
      }

      int main()
      {
      int arraytwo[2][2];
      int arraythree[3][3];

      pm_function(arr aytwo,2);
      pm_function(arr aythree,3);

      return 0;
      }

      Array names and pointers are only (more or less) interchangeable when the
      array is one dimensional (in the sense of having a single subscript). For
      two and more dimensions (in the sense of two or more subscripts) they are
      quite different.

      To illustrate, if pptr points to an int pointer, then pptr+1 is an address
      that is sizeof(int*) greater than pptr. By contrast, using the definition of
      arraythree given above, arraythree+1 yields an address that is 3*sizeof(int)
      greater than the address of arraythree. The difference is because pptr
      points to an int* pointer, whereas arraythree points to a row of three ints.

      To prove it, run the following code:

      int main()
      {
      int x;
      int *ptr = &x;
      int **pptr = &ptr;
      cout << "pptr address is " << pptr << '\n';
      cout << "pptr+1 address is " << pptr+1 << '\n';

      int arraythree[3][3];

      cout << "arraythree address is " << arraythree << '\n';
      cout << "arraythree +1 address is " << arraythree+1 << '\n';


      return 0;
      }

      If you want to pass 2-dimensional arrays to a function, then you need to a
      different function for each different column count. Templates can help here.


      --
      John Carson


      Comment

      • Klaas Vantournhout

        #4
        Re: matrix of function pointers

        >> //function[color=blue][color=green]
        >> void pm_function(voi d (***f) (int), int dim) {
        >> for (int i = 0; i < dim; i++)
        >> for (int j = 0; j < dim; j++)
        >> f[i][j](5);
        >> }
        >>
        >> int main(void) {
        >> void (*f[2][2])(int);
        >> void (*g[3][3])(int);[/color]
        >
        > You realise of course that you have never initialised these function
        > pointers to point to anything.[/color]

        Yes I do ;-)

        [color=blue][color=green]
        >> // I want this to work, but it doesn not! See error above message
        >> pm_function(f,2 );
        >> pm_function(g,3 );
        >>
        >> }[/color]
        >[/color]
        [color=blue]
        > Your problem is not specifically with function pointers. You would have the
        > same problem with arrays of ints, e.g., the following won't compile for the
        > same reason.[/color]
        <snip>[color=blue]
        > If you want to pass 2-dimensional arrays to a function, then you need[/color]
        to a[color=blue]
        > different function for each different column count. Templates can help here.[/color]

        I am indeed aware of this. That is why I would like to define my matrix
        of function pointers using dynamical allocation using the new operator.
        This should sort that problem out and let me use a double pointer in
        the function call.

        The answer given by benben is indeed a solution. But I was wondering if
        you could do it without defining a new type.

        Already thanks for your swift response.

        klaas

        Comment

        • JoShCrUz

          #5
          Re: matrix of function pointers

          I think you should go back to basics, first the work out the pointers
          to functions:

          #ifdef HAVE_CONFIG_H
          #include <config.h>
          #endif

          #include <iostream>
          #include <cstdlib>

          using namespace std;
          //-----------------------------------------------------------------------------
          // define the type
          typedef void (*Tpointer2Func tion)(int);
          // define the array with 3 elements
          Tpointer2Functi on ArrayOfFunction s[3];
          //-----------------------------------------------------------------------------
          void function1(int a)
          {
          cout << "function 1 = " << a << endl;
          }
          //-----------------------------------------------------------------------------
          void function2(int a)
          {
          cout << "function 2 = " << a << endl;
          }
          //-----------------------------------------------------------------------------
          void function3(int a)
          {
          cout << "function 3 = " << a << endl;
          }
          //-----------------------------------------------------------------------------
          int main(int argc, char *argv[])
          {
          // assign the functions you want to call to the array
          ArrayOfFunction s[0] = function1;
          ArrayOfFunction s[1] = function2;
          ArrayOfFunction s[2] = function3;
          // iterate thru the array
          for (int i=0; i <=2; i++)
          {
          ArrayOfFunction s[i](i);
          }
          return EXIT_SUCCESS;
          }
          //-----------------------------------------------------------------------------

          Once you've done that you could go and have a dynamic array (see Bruce
          Eckel's 'thinking in c++' 2nd edition - "Arrays of pointers to
          functions" section - with minor modifications):

          #include <iostream>
          #include <cstdlib>

          using namespace std;
          //-----------------------------------------------------------------------------
          // A macro to define dummy functions - Bruce's functions have no int
          parameter;
          #define DF(N) void N(int a) { cout << "function " #N " called with
          parameter " << a << endl; }

          DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g);

          void (*func_table[])(int) = {a, b, c, d, e, f, g};
          //-----------------------------------------------------------------------------
          int main(int argc, char *argv[])
          {
          while (true)
          {
          char c, cr;
          cout << "press a key from 'a' to 'g' or 'q' to quit" << endl;
          cin.get(c); cin.get(cr); // second one for CR
          // another alteration LValues are better there so you don't get
          assignments
          // rather than comparisons
          if ('q'== c)
          break;
          if (c < 'a' || c > 'g')
          continue;
          (*func_table[c - 'a'])(101);
          }
          return EXIT_SUCCESS;
          }
          //-----------------------------------------------------------------------------

          Comment

          • Klaas Vantournhout

            #6
            Re: matrix of function pointers

            benben wrote:[color=blue]
            >
            > Maybe the following code would help:
            >
            > typedef void (*fnptr)(int);
            > typedef fnptr** fnptr_mtrx;
            >
            > fnptr_mtrx matrix = ...[/color]


            Thanks benben for the swift response,

            But is this possible without redefining a new type?

            In your declaration fnptr_mtrx is indeed of the type void (***)(int);

            using your declartion I would be able to do
            fnptr_mtrx = new fnptr *[n];
            for (int i = 0; i < n; i++)
            fnptr[i] = new fnptr [m];

            to construct an n x m function pointer matrix, but is it possible to
            write something like

            void (***g)(int);
            g = new void (**)(int) *[5];

            or anything like that? (the above does not work)

            klaas

            Comment

            • John Carson

              #7
              Re: matrix of function pointers

              "Klaas Vantournhout" <no_valid_email @spam.com> wrote in message
              news:dvm73e$g82 $1@gaudi2.UGent .be[color=blue]
              >
              > I am indeed aware of this. That is why I would like to define my
              > matrix of function pointers using dynamical allocation using the new
              > operator. This should sort that problem out and let me use a double
              > pointer in the function call.
              >
              > The answer given by benben is indeed a solution. But I was wondering
              > if you could do it without defining a new type.
              >
              > Already thanks for your swift response.
              >
              > klaas[/color]

              A typedef does not introduce a new type. It is simply an alias for a type.

              You can do dynamic allocation of function pointers without using a typedef,
              but it is pointlessly difficult to do so.

              Just for the record:

              #include <iostream>

              using namespace std;

              // function to which function pointers will point
              template<int n>
              void func(int x)
              {
              cout << n*x << '\n';
              }

              // your (modified) function
              void pm_function(voi d (*(*(*f)))(int) , int dim)
              {
              for (int i = 0; i < dim; i++)
              for (int j = 0; j < dim; j++)
              f[i][j](5);
              }



              int main()
              {
              // dynamic pointer allocation

              void (*(*(*g)))(int) = new (void (*(*[3]))(int));

              for(int i=0; i<3; ++i)
              g[i] = new (void (*[3])(int));

              // initialise function pointers
              for(int i=0; i<3; ++i)
              {
              for(int j=0; j<3; ++j)
              {
              switch(i)
              {
              case 0:
              g[i][j]=&func<0>;
              break;
              case 1:
              g[i][j]=&func<1>;
              break;
              case 2:
              g[i][j]=&func<2>;
              break;
              }
              }
              }

              // test your function
              pm_function(g,3 );

              // cleanup

              for(int i=0; i<3; ++i)
              delete[] g[i];

              delete[] g;

              return 0;
              }

              If you think this is good code, then we have very different ideas of what
              constitutes good code.


              --
              John Carson




              Comment

              • Klaas Vantournhout

                #8
                Re: matrix of function pointers

                > A typedef does not introduce a new type. It is simply an alias for a type.

                Indeed, my mistake there
                [color=blue]
                > You can do dynamic allocation of function pointers without using a typedef,
                > but it is pointlessly difficult to do so.
                >
                > Just for the record:[/color]

                <snip>[color=blue]
                > void (*(*(*g)))(int) = new (void (*(*[3]))(int));
                >
                > for(int i=0; i<3; ++i)
                > g[i] = new (void (*[3])(int));[/color]

                <snip>
                [color=blue]
                > If you think this is good code, then we have very different ideas of what
                > constitutes good code.[/color]

                Why should this not be good code? I dislike the use of typedef because
                it makes things sometimes unreadable. It is to my opinion only usefull
                when you have an extreme long annoying type which you have to declare
                multiple times.

                Here this is not the case, you can see immediately of what type 'g' is.
                And it is not much more difficult then using a typedef. The
                initialisation is done in the same way.

                Or did you mean something else?

                I used this in my code because I could reduce 300 lines of code to only
                20 with this. Removed a big mixture of case and if conditions which was
                totally unreadable. And also the size of the matrix depends on the
                initial conditions of my program.

                Thanks again for the answer. You made my day!

                klaas

                Comment

                • John Carson

                  #9
                  Re: matrix of function pointers

                  "Klaas Vantournhout" <no_valid_email @spam.com> wrote in message
                  news:dvock7$8k0 $1@gaudi2.UGent .be[color=blue][color=green]
                  >> A typedef does not introduce a new type. It is simply an alias for a
                  >> type.[/color]
                  >
                  > Indeed, my mistake there
                  >[color=green]
                  >> You can do dynamic allocation of function pointers without using a
                  >> typedef, but it is pointlessly difficult to do so.
                  >>
                  >> Just for the record:[/color]
                  >
                  > <snip>[color=green]
                  >> void (*(*(*g)))(int) = new (void (*(*[3]))(int));
                  >>
                  >> for(int i=0; i<3; ++i)
                  >> g[i] = new (void (*[3])(int));[/color]
                  >
                  > <snip>
                  >[color=green]
                  >> If you think this is good code, then we have very different ideas of
                  >> what constitutes good code.[/color]
                  >
                  > Why should this not be good code? I dislike the use of typedef
                  > because it makes things sometimes unreadable. It is to my opinion
                  > only usefull when you have an extreme long annoying type which you
                  > have to declare multiple times.
                  >
                  > Here this is not the case, you can see immediately of what type 'g'
                  > is.[/color]


                  I doubt that 1 in 100 C++ programmers can "see immediately what type g is".
                  I couldn't do so myself if I hadn't written the code.

                  Compare:

                  typedef void (*FnPtr)(int);

                  FnPtr **g = new FnPtr*[3];

                  for(int i=0; i<3; ++i)
                  g[i] = new FnPtr[3];

                  Once you make the typedef, this looks just like what you would do if you had
                  an array of ints or doubles. It is familiar and easy to comprehend.


                  --
                  John Carson


                  Comment

                  Working...