开发者

How to make a function receive multidimentional array of arbitrary size in C++?

I was trying to make a function which takes a matrix as开发者_开发百科 input and outputs some function of it in C++. But I want it to work on arbitrary size mxn matrix. i.e. I cannot specify in the arguments of the function the values of n (double matrix[][n]) . Because n will be arbitrary. Is there any way I can pass on an arbitrary mxn 2 dimensional array to a function? Thanking you in advance. -indiajoe


template <typename T, size_t W, size_t H>
void foo(T (&array)[W][H]) {
   // Do stuff with array here
}


There is more than one way to do it. The best way is probably to define a matrix class and to pass a const reference to an instance.

class matrix
{
    double* values;
    size_t m;
    size_t n;
public:
    matrix(size_t m_, size_t n_)
    : m(m_), n_(n)
    {
        values = new double[m * n];
    }

    ~matrix()
    {
        delete[] values;
    }

    double& operator(size_t i, size_t j)
    {
        assert(i < m);
        assert(j < n);
        return values[i + m * j];
    }

    const double& operator(size_t i, size_t j) const
    {
        assert(i < m);
        assert(j < n);
        return values[i + m * j];
    }
private:
    matrix(const matrix&);
    matrix& operator =(const matrix&);
};

void function(const matrix& matrix);

If you don't want to use a class, and your data is stored linearly (as in my matrix class), you can simply pass a pointer to a double, and the dimensions:

void function(double* values, size_t m, size_t n);

If you really want to use double[m][n] and have a function accepting any matrix size, you can convert it manually to a double**, by doing something like that:

void function(double** lines, size_t m, size_t n);

void client()
{
    const size_t m = ...;
    const size_t n = ...;
    double matrix[m][n];

    double* temporary[m];
    for (size_t i = 0; i < m; ++ i) {
        temporary[i] = &matrix[i][0];
    }

    function(temporary, m, n);
}

Or, using a template function to do the conversion:

void function(double** array, size_t m, size_t n);

template < size_t M, size_t N >
void function(double array[M][N]) {
    double* temporary[M];
    for (size_t i = 0; i < M; ++ i) {
        temporary[i] = &array[i][0];
    }
    function(temporary, M, N);
}

This is because an array can only decay once to a pointer (that is double[n] decay to double* but double[m][n] decay to double*[n]).


using the Standard C++ Library, you could do that:

typedef std::vector<double> Dim;
typedef std::vector<Dim> Matrix;

void workOnMatrix(Matrix& matrix)
{

}

EDIT: I remove the reference to STL since SGI's STL and the Standard C++ Library are not the same things. So much different it seems that they must not be taken one for another.


You could do it Tomalak's way, but I certainly wouldn't recommend it. You could never call that function from within another that wasn't also a template if the array was passed through params. This means almost your entire program would have to be templated code. OK, in theory, but generally impractical.

You can't use the double** interface as you've found out. You could cast to that type but then you also need the size information to be passed in so that you can:

my_ptrptr[row * col_size][col];

You have to be explicit about the dimensions like this because the compiler no longer knows what it needs to.

The best answer to your problem is to not do it that way. Leverage the STL so that you don't have to deal with hokey crap like this. Use Stephane's answer.

Yet another thing you can do though, if you're going to use templates anyway, is to write it to be generic:

template < typename Iter >
void fun(Iter begin, Iter end)
{
  // begin[x][y]... (*begin)[y]...++begin, etc...
}
...
double arr[arr_row_count][arr_col_count];
fun(arr, arr+arr_row_count);

This one has the major benefit of working with ANYTHING that looks like an array of arrays. This means it would make an excellent 'interim' method that you can use with your double[][] types until such time as you can begin using something better like the std::vector and/or boost::array. Do it Tomalak's way and you won't be able to make this change later...yet another reason not to use that method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜