Array of point to arrays of different size

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Edward Jensen

    #1

    Array of point to arrays of different size

    Hi,

    I have the following static arrays of different size in a class:

    in header:
    static double w2[2], x2[2];
    static double w3[3], x3[3];
    static double w4[4], x4[4];

    in GaussLegendre.c pp:
    double GaussLegendre:: w2[2] = {1.0, 1.0};
    double GaussLegendre:: x2[2] = {-0.5773502691896 25, 0.5773502691896 25};
    double GaussLegendre:: w3[3] = {0.555555555555 556, 0.8888888888888 889,
    0.5555555555555 56};
    double GaussLegendre:: x3[3] = {-0.7745966692414 83, 0.0, 0.7745966692414 83};
    double GaussLegendre:: w4[4] = {0.347854845137 453, 0.6521451548625 46,
    0.6521451548625 46, 0.3478548451374 53};
    double GaussLegendre:: x4[4] = {-0.8611363115940 53, -0.3399810435848 56,
    0.3399810435848 56, 0.8611363115940 53};

    Now I want to create a static array of pointers of x2, x3, x4 and w2,w2,w4.
    I thought I could do that with just
    declaring statis double* x[3] in my header and the following in .cpp:

    double* GaussLegendre:: x[3] = {&GaussLegendre ::x2, &GaussLegendre: :x3,
    &GaussLegendre: :x4};

    but I get the following error: cannot convert from 'double (*)[2]' to
    'double *

    Why is that and how can it be done?

    Thanks in advance,
    Edward


  • Sam

    #2
    Re: Array of point to arrays of different size

    Edward Jensen writes:
    Hi,
    >
    I have the following static arrays of different size in a class:
    >
    in header:
    static double w2[2], x2[2];
    static double w3[3], x3[3];
    static double w4[4], x4[4];
    >
    in GaussLegendre.c pp:
    double GaussLegendre:: w2[2] = {1.0, 1.0};
    double GaussLegendre:: x2[2] = {-0.5773502691896 25, 0.5773502691896 25};
    double GaussLegendre:: w3[3] = {0.555555555555 556, 0.8888888888888 889,
    0.5555555555555 56};
    double GaussLegendre:: x3[3] = {-0.7745966692414 83, 0.0, 0.7745966692414 83};
    double GaussLegendre:: w4[4] = {0.347854845137 453, 0.6521451548625 46,
    0.6521451548625 46, 0.3478548451374 53};
    double GaussLegendre:: x4[4] = {-0.8611363115940 53, -0.3399810435848 56,
    0.3399810435848 56, 0.8611363115940 53};
    >
    Now I want to create a static array of pointers of x2, x3, x4 and w2,w2,w4.
    I thought I could do that with just
    declaring statis double* x[3] in my header and the following in .cpp:
    >
    double* GaussLegendre:: x[3] = {&GaussLegendre ::x2, &GaussLegendre: :x3,
    &GaussLegendre: :x4};
    >
    but I get the following error: cannot convert from 'double (*)[2]' to
    'double *
    >
    Why is that and how can it be done?
    This is because x is an "array of pointers to double", so each element of x
    is a "pointer to a double", or a "double *".

    The type of x2 is a array of two doubles, or double[2], so when you take a
    pointer to it, &x2, you get a pointer to an array of two doubles, or double
    (*)[2], which cannot be converted to a "double 2". That's what the compiler
    is telling you.

    Recall that "an array of type X" can be automatically converted to a
    "pointer to X". So, 'x2' can be automatically converted to "double *",
    without any further gymnastic. In other words, lose the "&":

    double* GaussLegendre:: x[3] = {GaussLegendre: :x2, GaussLegendre:: x3,
    GaussLegendre:: x4};


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.9 (GNU/Linux)

    iEYEABECAAYFAkk eCQoACgkQx9p3GY HlUOJL7gCaAvnZl weWfifdOfmiqyMm 2DEH
    8AAAn2NXKT7XMA3 t3UGiaVKg8u9l8d 3d
    =+e7a
    -----END PGP SIGNATURE-----

    Comment

    • Salt_Peter

      #3
      Re: Array of point to arrays of different size

      On Nov 14, 4:57 pm, "Edward Jensen" <edw...@jensen. invalidwrote:
      Hi,
      >
      I have the following static arrays of different size in a class:
      >
      in header:
      static double w2[2], x2[2];
      static double w3[3], x3[3];
      static double w4[4], x4[4];
      >
      in GaussLegendre.c pp:
      double GaussLegendre:: w2[2] = {1.0, 1.0};
      double GaussLegendre:: x2[2] = {-0.5773502691896 25, 0.5773502691896 25};
      double GaussLegendre:: w3[3] = {0.555555555555 556, 0.8888888888888 889,
      0.5555555555555 56};
      double GaussLegendre:: x3[3] = {-0.7745966692414 83, 0.0, 0.7745966692414 83};
      double GaussLegendre:: w4[4] = {0.347854845137 453, 0.6521451548625 46,
      0.6521451548625 46, 0.3478548451374 53};
      double GaussLegendre:: x4[4] = {-0.8611363115940 53, -0.3399810435848 56,
      0.3399810435848 56, 0.8611363115940 53};
      >
      Now I want to create a static array of pointers of x2, x3, x4 and w2,w2,w4.
      I thought I could do that with just
      declaring statis double* x[3] in my header and the following in .cpp:
      >
      double* GaussLegendre:: x[3] = {&GaussLegendre ::x2, &GaussLegendre: :x3,
      &GaussLegendre: :x4};
      >
      but I get the following error: cannot convert from 'double (*)[2]' to
      'double *
      >
      Why is that and how can it be done?
      >
      Thanks in advance,
      Edward
      You can point to a double using a double*, you certainly can't point
      to an array of doubles of varying sizes. You can however point to the
      first element of each array. Something as follows:

      double* GaussLegendre:: x[3] = { &GaussLegendre: :x2[0],
      &GaussLegendre: :x3[0],
      &GaussLegendre: :x4[0] };

      However, the elements of x know nothing about the contents of the
      arrays that are part of.
      To solve the issue, use dynamic containers. Lets take a std::deque of
      std::vectors< double for example (ignore the operator<< for now - it
      just displays the populated containers). Notice how much simpler
      coding without pointers is.

      #include <iostream>
      #include <ostream>
      #include <deque>
      #include <vector>
      #include <algorithm>
      #include <iterator>

      namespace D
      {
      std::deque< std::vector< double dvd;
      }

      template < typename T >
      std::ostream& operator<<( std::ostream& os,
      std::deque< std::vector< T & r_d )
      {
      typedef typename std::deque< std::vector< T ::iterator DIter;
      for( DIter iter = r_d.begin(); iter != r_d.end(); ++iter )
      {
      std::copy( (*iter).begin() ,
      (*iter).end(),
      std::ostream_it erator< T >( os, " ") );
      os << std::endl;
      }
      return os;
      }

      int main()
      {
      using namespace D;

      std::vector< double v1(10, 1.1); // 10 elements all initialized
      std::vector< double v2(11, 2.2);
      std::vector< double v3(12, 3.3);

      dvd.push_back( v1 );
      dvd.push_back( v2 );
      dvd.push_back( v3 );

      std::cout << dvd;
      }

      /*
      1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1
      2.2 2.2 2.2 2.2 2.2 2.2 2.2 2.2 2.2 2.2 2.2
      3.3 3.3 3.3 3.3 3.3 3.3 3.3 3.3 3.3 3.3 3.3 3.3
      */

      // Both the elements (std::vector< double >) and the deque itself
      remain dynamic.

      dvd[0].push_back( 9.9 ); // add an eleventh double to 1st collection

      // How about loading a std::deque named d1 with
      // four std::vector< double containers
      // all having 10 elements initialized to 0.1:

      std::deque< std::vector< double d1(4, std::vector< double >(10,
      0.1));

      // Thats one line, and the containers remain dynamic.
      // Still thinking of using primitive arrays and pointers?

      Comment

      • Andrey Tarasevich

        #4
        Re: Array of point to arrays of different size

        Edward Jensen wrote:
        >
        Now I want to create a static array of pointers of x2, x3, x4 and w2,w2,w4.
        I thought I could do that with just
        declaring statis double* x[3] in my header and the following in .cpp:
        >
        double* GaussLegendre:: x[3] = {&GaussLegendre ::x2, &GaussLegendre: :x3,
        &GaussLegendre: :x4};
        >
        but I get the following error: cannot convert from 'double (*)[2]' to
        'double *
        >
        Why is that
        In C and C++, when you apply the unary '&' to an array, you get a value
        of pointer-to-array type. For example, if array 'a' is declared as

        int a[10];

        the expression '&a' has type 'int (*)[10]' - a pointer to an array of 10
        'int's

        int (*pa)[10] = &a; // OK

        This type is not convertible to 'int*'

        int *pi = &a; // ERROR

        This is exactly the error your code produces.
        and how can it be done?
        Since you are trying to point to arrays of _different_ sizes, using
        pointers of pointer-to-array type is not an option. Instead, just use an
        array of "regular" pointers (which is what you have already) and make
        the point to the very first element of each array

        double* GaussLegendre:: x[3] = {
        &GaussLegendre: :x2[0],
        &GaussLegendre: :x3[0],
        &GaussLegendre: :x4[0]
        };

        or alternatively (and equivalently)

        double* GaussLegendre:: x[3] = {
        GaussLegendre:: x2,
        GaussLegendre:: x3,
        GaussLegendre:: x4
        };

        (note that there's no '&' operator in the latter case).

        --
        Best regards,
        Andrey Tarasevich

        Comment

        • James Kanze

          #5
          Re: Array of point to arrays of different size

          On Nov 15, 12:59 am, Salt_Peter <pj_h...@yahoo. comwrote:
          On Nov 14, 4:57 pm, "Edward Jensen" <edw...@jensen. invalidwrote:
          I have the following static arrays of different size in a class:
          in header:
          static double w2[2], x2[2];
          static double w3[3], x3[3];
          static double w4[4], x4[4];
          in GaussLegendre.c pp:
          double GaussLegendre:: w2[2] = {1.0, 1.0};
          double GaussLegendre:: x2[2] = {-0.5773502691896 25, 0.5773502691896 25};
          double GaussLegendre:: w3[3] = {0.555555555555 556, 0.8888888888888 889,
          0.5555555555555 56};
          double GaussLegendre:: x3[3] = {-0.7745966692414 83, 0.0, 0.7745966692414 83};
          double GaussLegendre:: w4[4] = {0.347854845137 453, 0.6521451548625 46,
          0.6521451548625 46, 0.3478548451374 53};
          double GaussLegendre:: x4[4] = {-0.8611363115940 53, -0.3399810435848 56,
          0.3399810435848 56, 0.8611363115940 53};
          So presumably that bit in header was within the defintion of the
          class GaussLegendre.
          Now I want to create a static array of pointers of x2, x3,
          x4 and w2,w2,w4. I thought I could do that with just
          declaring statis double* x[3] in my header and the following
          in .cpp:
          double* GaussLegendre:: x[3] = {&GaussLegendre ::x2, &GaussLegendre: :x3,
          &GaussLegendre: :x4};
          but I get the following error: cannot convert from 'double (*)[2]' to
          'double *
          You should get an error about defining a variable twice, and/or
          defining it with a different type than it was declared with.
          Why is that and how can it be done?
          You can point to a double using a double*, you certainly can't
          point to an array of doubles of varying sizes. You can however
          point to the first element of each array. Something as
          follows:
          double* GaussLegendre:: x[3] = { &GaussLegendre: :x2[0],
                                          &GaussLegendre: :x3[0],
                                          &GaussLegendre: :x4[0] };
          That's certainly legal, but it's far more idiomatic to use the
          implicit conversion of array to pointer here, as Sam suggested.
          While it may be a misfeature, it's use is ubiquious, and
          unavoidable if you are using C style arrays.
          However, the elements of x know nothing about the contents of the
          arrays that are part of.
          Which is as it should be. (But I think you're trying to say
          something else. You surely don't mean that the value in x[1]
          should know something about x as a whole.)
          To solve the issue, use dynamic containers. Lets take a
          std::deque of std::vectors< double for example (ignore the
          operator<< for now - it just displays the populated
          containers). Notice how much simpler coding without pointers
          is.
          As a general rule, std::vector should be preferred, so his
          double[] would become std::vector<dou ble>, and he really can
          have an array of pointers to arrays, std::vector< std::vector<
          double >* >. I'd want to know more about his particular use,
          however, before doing that here. I have a sneaky suspicion that
          he's forgotten the const, and there is one place where C style
          arrays are better: they allow static initialization. If all of
          these tables are in fact const, it might make more sense (and it
          would certainly require less code) to leave them as C style
          arrays, i.e. something like:

          double const GaussLegendre:: w2[2] = {1.0, 1.0};
          // ...
          double const *const GaussLegendre:: x2[2] = { ... } ;

          Typically, I'd also leave off the size of the dimension, and
          let the compiler calculate it. But again, I'm not sure here; I
          think the actual size may be important, in which case, it's
          better explicitly stating it.

          --
          James Kanze (GABI Software) email:james.kan ze@gmail.com
          Conseils en informatique orientée objet/
          Beratung in objektorientier ter Datenverarbeitu ng
          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

          Comment

          Working...