Передача константных массивов с различными размерами в качестве параметров функции в C ++ - PullRequest
5 голосов
/ 03 января 2011

У меня постоянные многомерные массивы разных размеров. Я хотел бы передать их в функцию. Тем не менее, я получил бы ошибку отсутствующего индекса, размеры массивов разные, поэтому я не могу поместить индекс в параметр массива. Каково решение этой проблемы?

Вот пример кода. Фактические массивы больше.

//ARRAY1
const double ARRAY1[3][2][2] =
{
    {
        {1.0,1.0},
        {1.0,1.0},
    }
    ,
    {
        {1.0,1.0},
        {1.0,1.0},
    }
    ,
    {
        {1.0,1.0},
        {1.0,1.0},
    }
}
//ARRAY2
const double ARRAY2[2][2][2] =
{
    {
        {1.0,1.0},
        {1.0,1.0},
    }
    ,
    {
        {1.0,1.0},
        {1.0,1.0},
    }
}

//How to declare the parameter?
double SomeFunctionToWorkWithBothArrays(const double arr[][][])
{

}

Ответы [ 8 ]

14 голосов
/ 03 января 2011

Вы можете использовать шаблон.

template<size_t first, size_t second, size_t third> 
double SomeFunction(const double (&arr)[first][second][third]) {
    return first + second + third;
}

Эта функция принимает ссылку на трехмерный массив значений типа double, где все измерения известны во время компиляции.На самом деле можно взять эту ссылку через шаблон, если он в отчаянии.

5 голосов
/ 03 января 2011

Используйте std::vector вместо массивов. Векторы знают свой собственный размер, так что это не будет проблемой. Вы можете использовать векторы векторов в качестве многомерных массивов.

3 голосов
/ 03 января 2011

Вы можете либо использовать std::vector (размер которого является переменным и его не нужно указывать в типе), либо использовать статическое размещение и использовать шаблоны:

template <size_t X, size_t Y, size_t Z>
double SomeFunctionToWorkWithBothArrays(const double (&arr)[X][Y][Z])
{
   // A different version of this function will
   // exist for each combination of X, Y and Z.
}

(ВВ этом примере я предположил, что все три измерения могут отличаться.)

Также обратите внимание, что я передаю массив по ссылке;на самом деле не может передать массив по значению, так как аргумент свернется в указатель, а с многомерными массивами это немного усложняется.

Надеюсь, это поможет.

2 голосов
/ 03 января 2011

Вы можете использовать класс шаблона boost :: array и объявление функции шаблона для обработки этого.

РЕДАКТИРОВАТЬ: Просто добавить пример:

template<typename T, std::size_t I, std::size_t J, std::size_t K>
void MyFunction(const std::array<std::array<std::array<T, K>, J>, I>& data)
{
    // do something here
}

, который вы бы вызвали вманера:

std::array<std::array<std::array<T, 4>, 2>, 3> data; // which hopefully you have typedef'd somewhere to make the code more readable
MyFunction<double, 3, 2, 4>(data);
1 голос
/ 03 января 2011

Если переменным является только первое измерение (остальные измерения одинаковы для всех массивов), то вы все равно можете передавать массивы в одну и ту же функцию, поскольку вы можете оставить первое измерение массива в параметр функции.

double SomeFunctionToWorkWithBothArrays(const double arr[][2][2])
{

}

Если другие измерения также могут измениться, вам придется использовать другие функции, возможно созданные из одного шаблона, как показано в ответе @ DeadMG.

1 голос
/ 03 января 2011

Я знаю 2 подхода к этой проблеме:

  1. Используйте значение sentinel в качестве последней записи в массиве, например. {-1.0, -1.0}. Вам всегда нужно просто проверить первое значение в следующем крупном измерении
  2. Добавить дополнительный параметр (и) к функции, который указывает размер измерения, например. x, y, z или struct dim { int x, y, z};

С уважением,

Martin.

0 голосов
/ 21 марта 2017

На языке C просто определите свою функцию как

double func (size_t x, size_t y, size_t z, double arr[x][y][z])

Это возможно, потому что C (в отличие от C ++) имеет массивы переменной длины.

0 голосов
/ 03 января 2011

Если и только если расположение многомерных массивов определено стандартом (вопрос к гуру стандартов), вы можете сделать следующее:

в заголовке:

double SomeFunctionToWorkWithBothArraysInt(double const *data, int x, int y, int z);

template <size_t X, size_t Y, size_t Z>
double SomeFunctionToWorkWithBothArrays(double const (&arr)[X][Y][Z]) {
  SomeFunctionToWorkWithBothArraysInt(&arr, X, Y, Z);
}

в вашем файле .cpp:

double SomeFunctionToWorkWithBothArraysInt(double const *data, int x, int y, int z) {
  double res = 0.0;
  for (int xp = 0; xp < x; xp++) {
    for (int yp = 0; yp < y; yp++) {
      for (int zp = 0; zp < z; zp++) {
        res += data[(zp * y + yp) * x + xp]; // !!!ATTENTION!!!: This may be wrong if the array arrangement is different!
      }  
    }  
  }

  return res;
}

Преимущество состоит в том, что ваша "бизнес-логика" не создается при каждом создании функции шаблона и не предоставляется через файл заголовка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...