Для начала initarray
должен принимать аргумент float*
, а не void*
.
Когда вы конвертируете массив в указатель, вы теряете информацию о типе измерения. Вы действительно конвертируете его в указатель на первый элемент и признаете, что хранилище непрерывно.
char foo [2][2] = { {'a','b'}, {'c','d'} }; // Stored as 'a', 'b', 'c', 'd'
Вы можете сохранить информацию о размерах с помощью шаблонов.
template <int W, int H>
void initarray (float (&input)[W][H]) {
for (int x = 0; x < W; ++x) {
for (int y = 0; y < H; ++y) {
input [x][y] = INITDATAVAL;
}
}
}
int main () {
float array [3][4];
initarray (array);
}
Здесь input
является ссылкой на массив данного типа (а размерность является частью полного типа). Вывод аргумента шаблона приведет к перегрузке initarray
с W=3
, H=4
. Извините за жаргон, но вот как это работает.
Между прочим, вы не сможете вызвать эту версию initarray
с аргументом указателя, но вы можете предоставить перегрузки, если хотите. Я часто пишу такие вещи
extern "C" void process (const char * begin, const char * end);
template <typename N>
void process (const char * (&string_list) [N]) {
process (string_list, string_list + N);
}
Идея состоит в том, чтобы предоставить наиболее общий из возможных интерфейсов, реализовать его один раз в отдельном модуле перевода или библиотеке, или в любом другом месте, а затем предоставить более дружественные и безопасные интерфейсы.
const char * strings [] = {"foo", "bar"};
int main () {
process (strings);
}
Теперь, если я изменю strings
, мне не нужно менять код в другом месте. Мне также не нужно думать о раздражающих деталях, например, правильно ли я поддерживал NUMBER_OF_STRINGS=2
.