Array of point to arrays of different size

Discussion in 'C++' started by Edward Jensen, Nov 14, 2008.

  1. 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.cpp:
    double GaussLegendre::w2[2] = {1.0, 1.0};
    double GaussLegendre::x2[2] = {-0.577350269189625, 0.577350269189625};
    double GaussLegendre::w3[3] = {0.555555555555556, 0.8888888888888889,
    0.555555555555556};
    double GaussLegendre::x3[3] = {-0.774596669241483, 0.0, 0.774596669241483};
    double GaussLegendre::w4[4] = {0.347854845137453, 0.652145154862546,
    0.652145154862546, 0.347854845137453};
    double GaussLegendre::x4[4] = {-0.861136311594053, -0.339981043584856,
    0.339981043584856, 0.861136311594053};

    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
     
    Edward Jensen, Nov 14, 2008
    #1
    1. Advertising

  2. Edward Jensen

    Salt_Peter Guest

    On Nov 14, 4:57 pm, "Edward Jensen" <> wrote:
    > 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.cpp:
    > double GaussLegendre::w2[2] = {1.0, 1.0};
    > double GaussLegendre::x2[2] = {-0.577350269189625, 0.577350269189625};
    > double GaussLegendre::w3[3] = {0.555555555555556, 0.8888888888888889,
    > 0.555555555555556};
    > double GaussLegendre::x3[3] = {-0.774596669241483, 0.0, 0.774596669241483};
    > double GaussLegendre::w4[4] = {0.347854845137453, 0.652145154862546,
    > 0.652145154862546, 0.347854845137453};
    > double GaussLegendre::x4[4] = {-0.861136311594053, -0.339981043584856,
    > 0.339981043584856, 0.861136311594053};
    >
    > 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::eek:stream& operator<<( std::eek:stream& 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::eek:stream_iterator< 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?
     
    Salt_Peter, Nov 14, 2008
    #2
    1. Advertising

  3. 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
     
    Andrey Tarasevich, Nov 15, 2008
    #3
  4. Edward Jensen

    James Kanze Guest

    On Nov 15, 12:59 am, Salt_Peter <> wrote:
    > On Nov 14, 4:57 pm, "Edward Jensen" <> wrote:


    > > 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.cpp:
    > > double GaussLegendre::w2[2] = {1.0, 1.0};
    > > double GaussLegendre::x2[2] = {-0.577350269189625, 0.577350269189625};
    > > double GaussLegendre::w3[3] = {0.555555555555556, 0.8888888888888889,
    > > 0.555555555555556};
    > > double GaussLegendre::x3[3] = {-0.774596669241483, 0.0, 0.774596669241483};
    > > double GaussLegendre::w4[4] = {0.347854845137453, 0.652145154862546,
    > > 0.652145154862546, 0.347854845137453};
    > > double GaussLegendre::x4[4] = {-0.861136311594053, -0.339981043584856,
    > > 0.339981043584856, 0.861136311594053};


    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<double>, 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:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Nov 15, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    553
    Flash Gordon
    Apr 9, 2006
  2. Replies:
    8
    Views:
    510
    Bob Hairgrove
    Apr 10, 2006
  3. Philipp
    Replies:
    21
    Views:
    1,139
    Philipp
    Jan 20, 2009
  4. Saraswati lakki
    Replies:
    0
    Views:
    1,355
    Saraswati lakki
    Jan 6, 2012
  5. Timo
    Replies:
    1
    Views:
    196
    Vincent van Beveren
    Jun 14, 2004
Loading...

Share This Page