“自动”为 C++ 创建非成员包装器成员函数

发布于 2024-12-10 02:27:14 字数 1026 浏览 0 评论 0原文

我有一个带有一堆成员函数的类,它们执行一些数学运算并返回结果。例如:

class Foo {
public:
  double f(double);
  double g(double);
  double h(double);
  // ...
}

double Foo::f(double foo1) {
  // ...
}
// and so on

在我正在处理的程序中的几个点上,我需要对其中一些函数进行数值积分。我想使用的数值积分例程具有签名

extern "C" double qgauss(double (*func)(double, void*), void* data,
                         double a, double b);

,从我读到的内容来看,将成员函数传递给积分例程的最佳方法似乎是创建包装函数:

double f_wrapper(double x, void* data) {
    return ((Foo*)data)->f(x);
}

但是有大约十几个成员函数< code>f、gh 等进行换行,也许稍后会添加更多内容,这会变得非常重复。我可以(或者应该)使用模板或宏或其他东西来压缩我必须编写的代码量以创建这些包装器函数吗?


顺便说一句,我目前使用的解决方案是将集成例程重新实现为直接接受对象参数的 C++ 函数模板:

template <class C> double qgauss(C* obj, double (C::*func)(double),
                                 double a, double b) {
  // ...
}

但这涉及大规模的代码重复,这是我不喜欢的。如果有人有比创建包装器函数或实现 C++ 版本的集成器更好的解决方案,我将有兴趣听到它,并且我可以提出一个单独的问题是否更合适。

I have a class with a bunch of member functions which do some mathematical operation and return a result. For example:

class Foo {
public:
  double f(double);
  double g(double);
  double h(double);
  // ...
}

double Foo::f(double foo1) {
  // ...
}
// and so on

At several points in the program I'm working on, I need to numerically integrate some of these functions. The numerical integration routine I'd like to use has the signature

extern "C" double qgauss(double (*func)(double, void*), void* data,
                         double a, double b);

and from what I've been reading it seems that the best way to pass the member functions to the integration routine is to create wrapper functions:

double f_wrapper(double x, void* data) {
    return ((Foo*)data)->f(x);
}

But with about a dozen member functions f, g, h, etc. to wrap, and perhaps more to be added later, this gets pretty repetitive. Can (or perhaps should) I use a template or macro or something to condense the amount of code I have to write in order to create these wrapper functions?


As an aside, the solution I'm currently using is to reimplement the integration routine as a C++ function template that accepts the object parameter directly:

template <class C> double qgauss(C* obj, double (C::*func)(double),
                                 double a, double b) {
  // ...
}

but this involves large-scale duplication of code, which I don't like. If anyone has a better solution than either creating wrapper functions or implementing a C++ version of the integrator, I would be interested to hear it and I can ask a separate question if that would be more appropriate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

平定天下 2024-12-17 02:27:14

你可以用模板尝试一下:

template <class C, C::*Func>
double wrapper(double x, void* data) {
    return ((C*)data)->*Func(x);
}

qgauss(&wrapper<C, &C::f>, data, a, b);

现在,我还没有尝试过这个,可能会出现一些问题,因为你想要一个模板函数的地址——更糟糕的是,我认为你在技术上需要一个 extern ” C" 函数。如果上面确实是一个死胡同,我认为你应该只使用宏,因为毕竟这是你此时正在做的 C 编程,宏对此很自然。

You could try it with templates:

template <class C, C::*Func>
double wrapper(double x, void* data) {
    return ((C*)data)->*Func(x);
}

qgauss(&wrapper<C, &C::f>, data, a, b);

Now, I haven't tried this, and there may be some issue because you want the address of a function which is a template--and worse yet I think you technically need an extern "C" function. If the above is indeed a dead end, I think you should just use macros, as after all this is C programming you're doing at this point, and macros are natural for that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文