5argon
5argon

Reputation: 3863

Initialize c++ multi dimensional vector with multi dimensional array?

I have

  float viewerMatrix[4][4] =
    {
      {0.99962944, -0.023989394, -0.012864082, -0.032067116},
      {0.02354476, 0.9991557, -0.033667795, -0.0060634422},
      {0.013660891, 0.033352438, 0.99935031, 0.047027141},
      {   0, 0, 0, 1}
    };

I wanted to store this in a class, and there will be many more of these so I thought putting it in vector is a good idea. I need to convert this array into vector<vector<float>> and then after that push_back into a class member that is of type vector< vector<vector<float>> >.

So, can I initialize vector<vector<float>> with that array? What I tried

vector<vector<float>> floatVector (viewerMatrix);

Does not work.

error: invalid conversion from ‘float (*)[4]’ to ‘std::vector<std::vector<float> >::size_type {aka long unsigned int}’ [-fpermissive]

Upvotes: 2

Views: 1512

Answers (2)

fnc12
fnc12

Reputation: 2237

The problem of doing this is a memory layout: two dimensional C array [4][4] is located in memory as 16 (4*4) floats like float[16] array. But vector of vector located in other way: it is more similar like float** dynamic array and every element of type float* is allocated separately. It means you cannot just pass a pointer of your two dimensional array and be good. But you can use STL algorithms.

First of all std::vector and plain C array both are STL compatible. Let's say you need initialize std::vector with one dimentional C array. I must write something like this:

float testArray[4]={0.99962944, -0.023989394, -0.012864082, -0.032067116};
vector<float> testVector(testArray,testArray+4);

It will construct a new vector and iterate from testArray (it's a pointer) to testArray+4 (it's a pointer too) and push_back every element into testVector. So the easiest way to achieve what you want is:

vector<vector<float>> floatVector{
    {viewerMatrix[0],viewerMatrix[0]+4},
    {viewerMatrix[1],viewerMatrix[1]+4},
    {viewerMatrix[2],viewerMatrix[2]+4},
    {viewerMatrix[3],viewerMatrix[3]+4},
};

Of course 4 value in dimensions can be changed so it is better to create a function that takes a two dimensional array of any number of elements and returns std::vector<std::vector<float>>. For example:

template<size_t M,size_t N>
std::vector<std::vector<float>> initVectorWithTwoDimArray(float (&ar)[M][N]){
    std::vector<std::vector<float>> res;
    res.reserve(M);
    for(auto i=0;i<M;++i){
        res.emplace_back(ar[i],ar[i]+N);
    }
    return std::move(res);
}

float viewerMatrix[4][4] =
{
    {0.99962944, -0.023989394, -0.012864082, -0.032067116},
    {0.02354476, 0.9991557, -0.033667795, -0.0060634422},
    {0.013660891, 0.033352438, 0.99935031, 0.047027141},
    {   0, 0, 0, 1}
};

auto floatVector=initVectorWithTwoDimArray(viewerMatrix);

Now floatVector is std::vector of std::vector<float> contained your two dim array.

Edit

If you like this function it can be recreated with array of any type not just float:

template<class T,size_t M,size_t N>
std::vector<std::vector<T>> initVectorWithTwoDimArray(T (&ar)[M][N]){
    std::vector<std::vector<T>> res;
    res.reserve(M);
    for(auto i=0;i<M;++i){
        res.emplace_back(ar[i],ar[i]+N);
    }
    return std::move(res);
}

This version will work for any type of arrays: int, double, AnyYourClass etc. Usage is the same:

float viewerMatrix[4][4] =
{
    {0.99962944, -0.023989394, -0.012864082, -0.032067116},
    {0.02354476, 0.9991557, -0.033667795, -0.0060634422},
    {0.013660891, 0.033352438, 0.99935031, 0.047027141},
    {   0, 0, 0, 1}
};

auto floatVector=initVectorWithTwoDimArray(viewerMatrix);

Upvotes: 2

M. Kolesnik
M. Kolesnik

Reputation: 33

You cannot have vector of array. If you really need to store the output in the vector, I would say make a something like

class Matrix
{
float m[4][4];
};

And then copy your stuff over and push it into the vector.

Upvotes: 1

Related Questions