感谢Bathsheba提供的提示,我终于想出了涉及函数指针的解决方案,我对此并不信任。主要问题是创建可能需要额外参数的特定功能。
注意:感谢joop,因此我们需要一个额外的函数调用,这可能会在宏解决方案中被忽略。
例如,这样的访问者重置具有给定值的所有矩阵元素。另一位访问者可能会使用一组参数修改元素,甚至不需要单个参数。所以基本上,我面临的问题是灵活定义vistor函数类型。
顺便说一句:在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);
}
可变参数功能:
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(对读者来说也是非显而易见的),如果你创建隐藏的变量,他们也不能嵌套。 – DaveRandom