matrixarray
 CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

#### Hybrid View

1. Member
Join Date
Mar 2010
Location
Melbourne Australia
Posts
454

## matrixarray

I wish to convert a 2D Array i.e int a[20][20] , convert to either s single array as in in[400] or hold it in a vector , and then back again , any ideas ?
my initial thoughts were

Code:
for(a to 200)
for(b to 200)
{
vector.push.back(int[a][b]); // this in sudo code ;
}

2. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

## Re: matrixarray

Originally Posted by aamir121a
I wish to convert a 2D Array i.e int a[20][20] , convert to either s single array as in in[400] or hold it in a vector , and then back again , any ideas ?
Code:
#include <algorithm>
#include <vector>

template <typename T>
struct VectorFrom2DArrayInitializer
{
typedef std::vector<T> TVector;
TVector & m_v;
int m_nElements;

VectorFrom2DArrayInitializer(TVector& theVector, int numElements) :
m_v(theVector), m_nElements(numElements) {}

void operator()(T *pElements)
{   m_v.insert(m_v.end(), pElements, pElements + m_nElements); }
};

template <typename T, int Rows, int Cols>
void Init1DVectorFrom2DArray(std::vector<T>& v, T arr[Rows][Cols])
{ std::for_each(arr, arr + Rows, VectorFrom2DArrayInitializer<T>(v, Cols)); }

int main()
{
// Initialize array to something
int a[20][20];
int counter = 0;
for (int i = 0; i < 20; ++i)
for (int j = 0; j < 20; ++j)
a[i][j] = counter++;

// set vector to the above array
std::vector<int> v;
Init1DVectorFrom2DArray<int, 20, 20>(v, a);
}
Well, this uses no loops except for the initializer for the array at the beginning of the test main() program.

It now doesn't matter if it's a 2d array of int, char, double, or Widgets. The 2d array of T is copied to the 1d vector of T using for_each() and a function object. Note that the only reliance on "int" is in the template argument to the Init1DVectorFrom2DArray function. Then everything there relies on type T, regardless of what T is.

Regards,

Paul McKenzie
Last edited by Paul McKenzie; December 2nd, 2012 at 02:13 AM.

3. Elite Member
Join Date
May 2009
Posts
2,413

## Re: matrixarray

Originally Posted by aamir121a
, any ideas ?
Instead of copying the arrays you can "overlay" them using a union,

Code:
union Same {
int a[50];
int b[10][5];
};
Here a and b represent the same 50 consecutive ints of memory, only they are accessed according to different matrix abstractions (and more can be added).

Code:
Same same; // static allocation at compile time
//
same.b[2][3] = 42;
std::cout << same.a[13] << std::endl;
It works because b[2][3] and a[13] represent the same memory position (2*5 + 3 = 13).

Since std::vector allocates memory dynamically a pointer must be used in that case. The above becomes,

Code:
std::vector<int> v(50); // dynamic allocation at runtime
Same* same = reinterpret_cast<Same*>(&v[0]); // sets Same pointer to start of vector data
//
same->b[2][3] = 42;
std::cout << same->a[13] << std::endl;
std::cout << v[13] << std::endl;
Last edited by nuzzle; December 3rd, 2012 at 05:00 AM.

4. Senior Member
Join Date
Oct 2008
Posts
1,456

## Re: matrixarray

Originally Posted by nuzzle
they are accessed according to different matrix abstractions (and more can be added).
I think this is not advisable; that use of unions relies on specific guarantees related to not-so-manifest properties of the types involved. Even with POD's you have to make sure that those member types have the same memory layout. Yes, with C++11 things have been relaxed to allow standard memory layout types with compatible layouts ( so, say, you could put there an std::array ) but it's still non trivial to check that the code is actually portable. So, I'd leave this technique to implementation details only.

5. Elite Member
Join Date
May 2009
Posts
2,413

## Re: matrixarray

Originally Posted by superbonzo
So, I'd leave this technique to implementation details only.
With different matrix abstractions I meant variations of 50 consecutive ints, like say

Code:
union Same {
int a[50];
int b[10][5];
int c[25][2];
int d[2][5][5];
// etcetera
};
To the best of my knowledge my suggestion is portable according to the C++ 11 standard (both regarding memory layout and the use of the reinterpret_cast).

But I agree that C-ish stuff like this shouldn't be all over the place in a C++ program.

6. Member
Join Date
Mar 2010
Location
Melbourne Australia
Posts
454

## Re: matrixarray

thank you

7. Elite Member Power Poster
Join Date
Apr 2000
Location
Belgium (Europe)
Posts
4,626

## Re: matrixarray

alternatvively... "why does it matter" ?
The data will ultimately be stored similarly, why does your code need to make a difference between 2D (or xD for that matter) or flat (1D) ?

If you have a need for a container that allows your data to be approached "flat" as well as 2d or 3d, then why not simply make a container like that. Make a template class that takes 2 dimentions, use it to make a X*Y vector, then provide members that can access the data either flat (with 1 index) or as a 2D array (with 2 indexes) (or as a 3D, 4D..... whatever).

8. ## Re: matrixarray

Originally Posted by OReubens
If you have a need for a container that allows your data to be approached "flat" as well as 2d or 3d, then why not simply make a container like that.
Yes, that's the way I'd approach it.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•