Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting 'Non-constant expression as array bound' when field is const

I'm trying to define a multidimensional array using my constant field as its dimension, but I'm getting a compilation error saying that the expression is not constant. Is there any other way to do this so I can use a constant field defined in constructor initialization list as an array dimension?

Translation for English-speaking majority:

class FunctionWave2D : public DisallowedDomainPoints
{
protected:
    double th; 
    double l; a
    double d, dd; 
    const int number_sqrt;  //here's the constant

    double **second_derivatives;

protected:
    bool elasticTenstionOnly;

public:
    FunctionWave2D(int number, double elasticModulus, double dampingFactor, double oscillationDampingFactor, double length)
        :DisallowedDomainPoints(number * LAYER_COUNT),
        th(elasticModulus), d(dampingFactor), dd(oscillationDampingFactor),
        elasticTensionOnly(false),
        l(length/(sqrt(number)-1)),
        number_sqrt(sqrt(number))
    {   
        second_derivatives = new double[number_sqrt][number_sqrt][LAYER_COUNT];
//(...)
like image 548
Natalia Zoń Avatar asked Dec 27 '22 01:12

Natalia Zoń


1 Answers

In C++, the term "constant expression" specifically refers to an expression whose value is known at compile-time. It's not the same as a const variable. For example, 137 is a constant expression, but in this code:

int function(int x) {
    const int k = x;
}

The value of k is not a constant expression, since its value can't be determined at compile-time.

In your case, you have a data member declared as

 const int ilosc_sqrt;  //here's the constant

Even though this is marked const, its value is not known at compile-time. It is initialized in the initializer list as

ilosc_sqrt(sqrt(ilosc))

This value can't be determined until the program is actually run, hence the error. (Note that the new C++11 constexpr keyword is designed, among other things, to make constant expressions a lot easier to identify in source code and to make it possible to do more advance compile-time computations with constants.)

To fix this, you will either need to split up your initialization into smaller steps:

drugie_pochodne = new double**[ilosc_sqrt];
for (int i = 0; i < ilosc_sqrt; i++) {
    drugie_pochodne[i] = new double*[ilosc_sqrt];
    for (int j = 0; j < ilosc_sqrt; j++) {
        drugie_pochodne[j] = new double[ILOSC_WARSTW];
    }
}

Or use a library like Boost.MultiArray, which supports a cleaner initialization syntax.

Hope this helps!

like image 197
templatetypedef Avatar answered Dec 29 '22 00:12

templatetypedef