Благодаря Bathsheba за предоставленные советы, я, наконец, придумал решения с указателями функций, с которыми я не уверен. Основная проблема заключается в создании конкретных функций, которые могут потребовать дополнительных параметров.
Примечание: Благодаря объединению мы нуждаемся в дополнительном вызове функции, который может быть опущен с помощью решения макроса.
Например, такой посетитель сбрасывает все элементы матрицы с заданным значением. Другой посетитель может изменять элементы с помощью набора параметров или даже не нуждаться в одном параметре. Поэтому в основном я сталкиваюсь с вопросом о гибком определении типа функции vistor.
BTW: В C++ это можно решить либо с помощью std::bind
, либо с помощью templates
.
Вложенные Функции:
Вложенные функции являются расширением GCC, и, например, недоступен в Clang.Тем не менее вот пример кода:
typedef double** Matrix;
typedef void (*MatrixElementVisitor) (double* element);
void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn) {
for(size_t i = 0; i < rows; ++i) {
for(size_t j = 0; j < cols; ++j){
fn(&m[i][j]);
}
}
}
void filM(Matrix m, size_t rows, size_t cols, double val) {
void fill(double *element) {
*element = val;
}
visitMatrixElements(m, rows, cols, fill);
}
VARIADIC функции:
typedef double** Matrix;
typedef void (*MatrixElementVisitor) (double* element, va_list args);
void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn, ...) {
va_list args,copy;
va_start(args, fn);
for(size_t i = 0; i < rows; ++i) {
for(size_t j = 0; j < cols; ++j){
va_copy(copy, args);
fn(&m[i][j], copy);
va_end(copy);
}
}
va_end(args);
}
void fill(double *element, va_list args) {
*element = va_arg(args, double);
}
void filM(Matrix m, size_t rows, size_t cols, double val) {
visitMatrixElements(m, rows, cols, fill, val);
}
недействительным указатель:
typedef double** Matrix;
typedef void (*MatrixElementVisitor) (double* element, void *args);
void visitMatrixElements(Matrix m, size_t rows, size_t cols, MatrixElementVisitor fn, void *args) {
if(m) {
for(size_t i = 0; i < rows; ++i) {
if(m[i]) {
for(size_t j = 0; j < cols; ++j){
fn(&m[i][j], args);
}
}
}
}
}
void fill(double* element, void *args) {
if(!args) {
return;
}
*element = *((double*)args);
}
void filM(Matrix m, size_t rows, size_t cols, double val) {
visitMatrixElements(m, rows, cols, fill, &val);
}
Может быть, существуют и другие способы, я думаю, с помощью статической функции переменные для инициализации функции посетителя, также включающие вариационные функции.
Благодарим Вас за отзыв.
Вы можете создать макрос, который будет генерировать эти циклы. – Crozin
Да, вы могли бы использовать функцию или макрос в этих случаях. –
Макрос, вероятно, будет либо беспорядочным (неочевидным для читателя), чтобы вызвать или создать фантомные скрытые «i» и «j» vars (также неочевидные для читателя). Если вы создаете скрытые vars, они также не может быть вложенным. – DaveRandom