Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to computinally initialize a const array(make const look-up-tables)?

Tags:

c++

c++11

Background: I'm stuck to arm-arago-linux-gnueabi-g++ (GCC) 4.3.3. Although answers that requires C++11 or later is also appreciated, please explicitly express any language requirement later than C++03.

The object's constructor fills values into tables to be used by the algorithm.

As those table does not change and are not supposed to be changed, I want the them to be const, how do I do that?

Difficulty #1, the values are computationally generated, and I don't want to hard code them in a source file.

Difficulty #2, the computing sometimes depends on inputs that are only available at runtime.

Difficulty #3, I don't know why but I don't want the array to be static, even though the values might be the same for all objects(cases where the values does not depend on runtime input).

Difficulty #4, it's an array, so initializer list in C++03 won't work.

Edit1: A few weeks after this post, I found both std::array and std::vector are very good alternative to C-style array when std::array is not available.

like image 774
user3528438 Avatar asked Sep 29 '22 23:09

user3528438


2 Answers

You can encapsulate the tables in a private type, with a single const instance of that type in your object, then forward the relevant constructor parameters to the private object; this works because even a const object is non-const during its construction.

For example:

class MyClass {
  const struct Tables {
    double x[1000];
    double y[200];
    Tables(int i, double d) {
      x[i] = d;
      y[200 - i] = -d;
    }
  } tables;
public:
  MyClass(int i, double d) : tables(i, d) {}
};
MyClass c(20, 5.5);

Another technique is to build the tables in an ephemeral mutable array whose lifetime is bounded by the lifetime of the constructor, then initialize the const array from those mutable arrays.

Using C++11 std::array (since array types can't be copy-initialized):

class MyClass {
    static std::array<double, 1000> buildArray(...) {
        std::array<double, 1000> array;
        ... // fill array
        return array;
    }
    const std::array<double, 1000> mArray;
public:
    MyClass(...) : mArray(buildArray(...)) {}
};

Note that std::array is easy to express in C++03; it doesn't depend on any C++11 language features.

If you're worried about the overhead of returning a large array, instrument it - even C++03 compilers are capable of optimising large array returns.

like image 117
ecatmur Avatar answered Oct 04 '22 03:10

ecatmur


I think you could implement a class containing the actual non const array. That way you can easily compute the values in a constructor.

Then this class would only have to implement the operator[] to be usable as an array. Or it could also simply return a const reference to the array.

Implementation example :

#include <iostream>
using namespace std;

class const_array {
    int *arr;
    size_t size;

public:
    const_array(size_t size, int typ): size(size) {
        arr = new int[size];
        size_t i;
        int val = 0;
        for (i=0; i<size; i++) {
            val += typ;
            arr[i] = val;
        }
    }
    const_array(const const_array & src): size(src.size) {
        arr = new int[size];
        size_t i;
        for (i=0; i<size; i++) {
            arr[i] = src.arr[i];
        }
    }
    ~const_array() {
        delete[] arr;
    }

    const int * const getArray() const {
        return arr;
    }
    int getSize() const {
        return size;
    }

    const int& operator[](int i) {
        return arr[i];
    }
};

int main() {
    const_array a(16, 4);
    // int *arr = a.getArray();  error
    const int *arr = a.getArray();
    int j = a[2];
    int k = arr[2];
    // int * pj = &(a[2]); error
    const int * pj = &(a[2]);
    const int * pk = &(arr[2]);
    cout << "a[2]=" << j << " (" << pj << ") - a.getArray[2]="
        << j << " (" << pj << ")" << endl;
    return 0;
}
like image 43
Serge Ballesta Avatar answered Oct 04 '22 03:10

Serge Ballesta