通过函数指针使用函数对象是必需的

时间:2011-11-18 15:40:00

标签: c++ function-pointers functor

我必须使用一些期望函数指针的遗留代码,比如说:

void LEGACY_CODE(int(*)(int))
{
    //...
}

然而,我所拥有的功能在一个仿函数中:

struct X
{
    Y member;       
    X(Y y) : member(y)
    {}

    int operator()(int)
    {
        //...
    }
};

我应该如何修改/包装类X,以便LEGACY_CODE可以访问X::operator()(int)中的功能?

4 个答案:

答案 0 :(得分:1)

你的问题毫无意义。你想打电话给谁的运营商?

X a, b, c;

LEGACY_CODE(???); // what -- a(), b(), or c()?

所以,简而言之,你不能。成员函数X::operator()不是该类的属性,而是与X类型的对象实例相关联。

在此网站搜索“成员函数”和“回调”,以了解相关问题的可能方法范围。


提供免费功能的最粗糙,可能不安全的解决方法是这样的:

X * current_X;  // ugh, a global
int dispatch(int n) { current_X->operator()(n); }

int main()
{
  X a;
  current_X = &a;
  LEGACY_CODE(dispatch);
}

你可以看到这是怎么回事......

答案 1 :(得分:0)

一个简单的包装函数如下所示:

int wrapperfunction(int i) {
    Functor f(params);
    return f(i);
}

如果您希望能够将参数传递给仿函数本身,最简单的方法是让他们使用(brr)全局变量:

Functor functorForWrapperfunction;
int wrapperfunction(int i) {
    functorForWrapperfunction(i);
}
// ...
void clientCode() {
    functorForWrapperfunction = Functor(a,b,c);
    legacyCode(wrapperfunction);
}

如果需要,可以使用带静态方法和静态成员的类来包装它。

答案 2 :(得分:0)

这是一个编译时解决方案。根据您的需要,这对您来说可能是一个限制太多的解决方案。

template<typename Func, int Param>
int wrapper(int i)
{
    static Func f(Param);
    return f(i);
}

答案 3 :(得分:0)

一种线程安全版本,受限于未在线程中使用不同参数调用遗留代码。

恕我直言,人们无法摆脱全球存储。

#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>

class AA
    {
    public:
        AA (int i) : i_(i) {}
        void  operator()(int j) const {
            static boost::mutex m; // do not garble output
            boost::mutex::scoped_lock lock(m);
            std::cout << " got " << j << " on thread " <<  i_ << std::endl; 
            Sleep(200); } 
        int i_;
    };

// LEGACY
void legacy_code(void (*f)(int), int i) {   (*f)(i);    }

// needs some global storage through
 boost::thread_specific_ptr<AA> global_ptr;

void func_of_thread(int j)
    {
    AA *a = global_ptr.get();
    a->operator()(j);
    }

void worker(int i)
{
 global_ptr.reset(new AA(i));
 for (int j=0; j<10; j++)
     legacy_code(func_of_thread,j);
    }


int main()
    {
    boost::thread worker1(worker,1) , worker2(worker,2);
    worker1.join(); worker2.join();
    return 0;
    }