0

I was wondering if there was a way to say pass this for example double MyArray[][2] = {{0.1,0.8},{0.4,0.6}} to a function like this void MyFunction(double myArray[][]);, without saying this void MyFunction(double myArray[][2]);. I need this because I want my function to be able to handle arrays with different inner dimensions for example: double MyArray[][3] = {{0.1,0.8},{0.4,0.6},{0.3,0.9}}. To pass this to a function as far as I know I would have to change MyFunctions's parameters to MyFunction(myArray[][3]);. From what I have read I don't know if this is possible, so if it is not then is there some other way of doing this?

MrQandA
  • 91
  • 1
  • 10

4 Answers4

4

You can pass an arbitrary 2d array by reference if you could change MyFunction to:

template<std::size_t N, std::size_t M>
void MyFunction(double (&myArray)[N][M]) {
  // ...
}

This way you would also have dimensions of the array.

101010
  • 39,010
  • 10
  • 84
  • 149
0

You can do it with templates:

template < size_t Dim >
void fun(double (*array)[Dim], size_t outerDim);

At this point though I'd seriously consider using either std::array or std::vector.

Edward Strange
  • 38,861
  • 7
  • 65
  • 123
0

C++ has dynamic arrays, they are called std::vector. You can use vectors of vectors, e.g.

typedef std::vector<std::vector<double> > DMatrix;

and pass objects of this type around just as you would do it with any other object, i.e.

void foo(const DMatrix& matrix){
    for (int i=0;i<matrix.size();i++){
        for (int j=0;j<matrix.size();j++){
            std::cout << matrix[i][j] << std::endl;
        }
    }
} 
463035818_is_not_a_number
  • 64,173
  • 8
  • 58
  • 126
0

This is an unusually common question.

Unfortunately, for straight arrays, you should do it the hard way.

First, you'll need a function to index an element of your mutli-dimensional array given the proper indices and dimensions. For a 2D array:

std::size_t index( std::size_t columns, std::size_t row, std::size_t column )
{
  return (row * columns) + column;
}

Note the lack of bounds-checking. You can add that if you like, but you should write code that doesn't need it. (Your function shouldn't need it, and the inline helper function will help your users not need it.)

Next, your function must work as in C -- taking an address of a flattened (one-dimensional) array and the dimensions. For example, here we'll print a const 2D array:

template <typename T>
void my_fn( const T* a, std::size_t rows, std::size_t columns )
{
  for (std::size_t r = 0; r < rows; r++)
  {
    for (std::size_t c = 0; c < columns; c++)
    {
      std::cout << a[ index( columns, r, c ) ] << " ";
    }
    std::cout << "\n";
  }
}

Finally, you'll want to make some inline functions that translate into a call to your general-purpose function:

template <typename T, std::size_t M, std::size_t N>
inline
void my_fn( const T (&a)[M][N] )
{
  return my_fn( (const T*)a, M, N );
}

Now you can use it with any 2D array:

int main()
{
  int xs[5][3];
  my_fn( xs );

  double ys[12][7];
  my_fn( ys );

Efficiency considerations:

  • Code for the templated function should only be generated once for each type; different dimensions of the same type will all use that same function.

  • The inline thunks should disappear completely -- optimized away by the compiler.

  • Addressing elements is no more complicated than it would be otherwise, and should be automagically optimized the same.

Hope this helps.

Dúthomhas
  • 4,323
  • 2
  • 11
  • 25