在方法中注入其他数据

时间:2012-10-05 09:27:57

标签: c++ code-injection

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

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::f2f2方法由另一位作者实现,代表了一些模拟算法(这里的例子是简化的)。

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)。但在我的情况下,需要在f1中为test()方法计算一些额外的参数

 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);

2 个答案:

答案 0 :(得分:1)

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

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

请记住,如果有多个线程使用这些功能,您需要使用线程本地存储(这是我建议的那个)或者确保适当的互斥使用这些变量,在这种情况下所有线程之间共享的单个变量意味着在调用链中一直排除。但如果线程出现问题,请使用线程本地存储。如果没有线程问题,那么,没问题! : - )

答案 1 :(得分:1)

  

没有肮脏的黑客

不会发生。如果你不能修改函数源的函数指针,你将不得不使用异常呕吐来获得额外的参数。如果你有一个支持thread_local的C ++ 11编译器(它还不存在),理论上可以做更好的事情,或者你可以使用特定于操作系统的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似乎并非不可能,只是很难。但是,将其更改为std::function<double(const TData&)>的难度非常低 - 所有您需要做的就是更改参数类型,这要归功于运算符重载。即使是复杂的函数也应该是一个非常简单的改变,因为你只是改变了函数参数的类型,所有的调用站点仍然可以工作,等等。然后你可以通过{{1}传递一个合适的函数对象。或者是一个lambda或者那么多。