Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: generate multidimensional vector of unknown depth

I have a function in C++ (call it "weightmatrix") that takes a vector of size n as input, which contains a series of numbers a, b, c..., and returns an n-dimensional vector made up of subvectors of size c, b, a...

That was complicated sounding. Basically, in practice it should look like this:

vector<int> vector_sizes = {2, 3, 1}; 
cout << "Resulting matrix: " << weightmatrix(vector_sizes); // Function takes vector of size 3
/* Returns the following 3 dimensional matrix:
   { { {0, 0}, 
       {0, 0}, 
       {0, 0} }, 
    {0, 0, 0} }
*/

It's a weird one, I know. I just need to generate a vector without knowing beforehand how many dimensions it will be. Any help or advice you could throw in my way would be awesome.

like image 732
L.C.J Avatar asked Oct 24 '25 04:10

L.C.J


1 Answers

Here is a solution using a template MultiVector class that returns a MultiVectorView from it's operator[].

The underlying data is stored in a plain std::vector but can be accessed with the vec[x][y][z] syntax.

There is no checking for correct usage, and only very basic functionality is implemented but it gives an idea how it could be done.

#include <iostream>
#include <vector>

template <typename T>
class MultiVector;

template <typename T>
class MultiVectorView {
public:
    MultiVectorView(MultiVector<T>& vec_, int index_, int dimension_) : vec(vec_), index(index_), dimension(dimension_) {}

    MultiVector<T>& vec;
    int index;
    int dimension;

    MultiVectorView& operator[](std::size_t n_index) {
        int index_multiplyer = 1;
        for (int i=0; i<dimension; ++i)
            index_multiplyer *= vec.dimensions[i];
        index += n_index*index_multiplyer;
        dimension++;
        return *this;
    }

    operator T() {
        return vec.content[index];
    }

    MultiVectorView& operator=(T val) {
        vec.content[index] = val;
        return *this;
    }
};

template <typename T>
class MultiVector {
public:
    MultiVector(std::vector<int> dimensions_) : dimensions(dimensions_) {
        int size = dimensions[0];
        for (int i = 1; i<dimensions.size(); ++i)
            size *= dimensions[i];

        content.resize(size);
    }

    MultiVectorView<T> operator[](std::size_t index) {
        return MultiVectorView<T>(*this, index, 1);
    }

    std::vector<T> content;
    std::vector<int> dimensions;
};

int main() {
    std::vector<int> v = {2,3,2};
    MultiVector<int> test(v);

    int tmp = 0;
    for (int x = 0; x < v[0]; ++x)
        for (int y = 0; y < v[1]; ++y)
            for (int z = 0; z < v[2]; ++z) {
                test[x][y][z] = tmp++;
            }

    for (int i=0; i<test.content.size(); ++i)
        std::cout << std::endl << test.content[i] << " ";

    int b = test[1][2][1];

    std::cout << std::endl << "b = " << b << std::endl << "test[0][1][1] = " << test[0][1][1] << std::endl;
}
like image 63
super Avatar answered Oct 25 '25 17:10

super



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!