Reputation: 5645
In Matlab it is possible to 'reshape' a (N-dimensional) matrix from any dimension to any other dimension, as long as the number of elements does not change. That is:
A = rand(10,10);
B = reshape(A, 100, 1);
Matlab can do so quite efficiently, because A and B still point to the same block of 100 doubles, they are only copied if one writes to either A or B: this is called copy-on-write.
I want this reshape feature in C/C++, that is, I want to be able to do this:
double flat[100];
double square[10][10] = ... flat ...;
such that square represents the same data, but interpreters indexing in another way.
In the end, what I want is syntax sugar, to do square[i][j] instead of square[10*i+j]. So, yes, writing some class that is able to share data with different dimensions (like matlab does) overloading indexing operators may do the yob. However, I am looking for a simpler solution.
On the other hand, I am afraid that the C++ standard(s) allow for compilers to implement dimensional arrays in different ways, disallowing for what I want. For example int[10][10] may be implemented as 10 blocks on 10 doubles and one block of 10 double pointers pointing to those. Moreover, I can create such a thing myself:
double **blowUp(double *array, int m, int n) {
double **r = new double[m];
for(int i=0; i<m; ++i, array+=n) r[i] = array;
return r;
}
but then the idea of syntax sugar disappears a bit, especially since I would need to clean up the wrapper array as well.
Another solution may be a templated subscript operator overload, where the the template arguments contain the first dimension of the data:
But as the compile errors suggest, this is not feasible without wrapping the data in a class structure. So, am I doomed to wrap data in a class and write a lot of boilerplate code if I want what I want? Please let me know what you think!
Upvotes: 2
Views: 2570
Reputation: 613163
The cleanest way to do this is to wrap the flat array in a class. You can implement use operator[]
to return a pointer to the ith row. The implementation of this operator[]
needs to know the shape which you wish to impose on the underlying array.
Upvotes: 2
Reputation: 7100
If you're using a simple array, this is quite easy using a reinterpret_cast
. Taking your example:
#include <iostream>
int main()
{
int flat[100];
for (int i=0; i<100; ++i)
flat[i]=i;
// now reinterpret that flat array as a 10x10 square
int (&square)[10][10] = *reinterpret_cast<int(*)[10][10]>(flat);
// print an arbitrary row
for (int i=0; i<10; ++i)
std::cout << square[5][i] << ' ';
std::cout << '\n';
}
This simple program prints:
50 51 52 53 54 55 56 57 58 59
Upvotes: 4