0

我正在一些大型库中添加新模块。这里的所有方法都是静态实现的。让我简单描述一下简化模型:

typedef std::vector<double> TData;
double test ( const TData &arg ) { return arg ( 0 ) * sin ( arg ( 1 ) + ...;}
double ( * p_test ) ( const TData> &arg) = &test;

class A
{
    public:
      static T f1 (TData &input) {
         .... //some computations
         B::f2 (p_test);
      }
};

在内部f1()执行一些计算并B::f2调用静态方法。该f2方法由另一位作者实现,代表了一些模拟算法(这里的例子是简化的)。

class B
{
    public:
      static double f2 (double ( * p_test ) ( const TData  &arg ) )
      {
          //difficult algorithm working p_test many times
          double res = p_test(arg);
      }
};

f2方法有一个指向某个权重函数的指针(这里p_test)。但在我的情况下,需要f1test()方法计算的一些额外参数

 double test ( const TData &arg, const TData &arg2, char *arg3.... ) { }

如何将这些参数注入test()(等等f2)以避免更改f2方法的源代码(这不是微不足道的),重新设计库并且没有肮脏的黑客:-)?

最简单的步骤是覆盖f2

static double f2 (double ( * p_test ) ( const TData  &arg ), const TData &arg2, char *arg3....  )

但是以后怎么办?考虑一下,方法是静态的,所以对象会有问题。


更新的问题

是否可以根据某些模板参数创建指向函数的指针或执行类似的操作

if (condition) res = p_test(arg);
else res = p_test2(arg, arg2, arg3);
4

2 回答 2

1

“避免改变”,这有点困难。

但是,您可以使用静态变量在不传递参数的函数调用之间传递参数。

请记住,如果有多个线程使用这些函数,您需要使用线程本地存储(这是我推荐的)或者确保正确互斥以使用这些变量,如果是单个变量在所有线程之间共享意味着沿着调用链一路排除。但如果线程有问题,请使用线程本地存储。如果没有线程问题,那么,没问题!:-)

于 2012-10-05T09:36:28.417 回答
1

没有肮脏的黑客

不会发生。如果您无法修改采用函数指针的函数的源代码,则必须使用异常呕吐物来获得额外的参数。如果您有一个支持 的 C++11 编译器(尚不存在),thread_local理论上可以做得更好,或者您可以使用特定于操作系统的 TLS。但截至目前,唯一可移植的解决方案是异常呕吐物。

void f(void(*fp)()) { fp(); }
void mah_func() { 
    try { 
        throw; 
    } catch(my_class* m) {
        m->func();
    }
}
int main() {
    my_class m;
    try {
        throw &m;
    } catch(my_class* p) {
        f(mah_func);
    }
}

或者,在您的场景中,修改f2似乎并非不可能,只是很困难。但是,将其更改为 a 的难度std::function<double(const TData&)>会非常低——您所要做的就是更改参数类型,这要归功于运算符重载。即使是复杂的函数,它也应该是一个非常简单的改变,因为你只是改变函数参数的类型,所有的调用站点仍然可以工作,等等。然后你可以传递一个适当的函数对象bind或一个 lambda 或某样的。

于 2012-10-05T09:44:47.880 回答