尽管需要函数指针,但使用函数对象

发布于 2024-12-16 23:22:51 字数 371 浏览 4 评论 0原文

我必须使用一些需要函数指针的遗留代码,比方说:

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

但是我拥有的功能是在函子内:

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

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

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

I have to use some legacy code expecting a function pointer, let's say:

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

However the functionality I have is within a functor:

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

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

How should I modify/wrap class X so that LEGACY_CODE can access the functionality within X::operator()(int) ?

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

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

发布评论

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

评论(4

彼岸花似海 2024-12-23 23:22:51

你的问题没有意义。您想致电谁的接线员?

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

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

Your question makes no sense. Whose operator do you want to call?

X a, b, c;

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

So, in short, you cannot. The member function X::operator() is not a property of the class alone, but rather it is tied to an object instance of type X.

Search this site for "member function" and "callback" to get an idea of the spectrum of possible approaches for related problems.


The crudest, and quite possibly not-safe-for-use, workaround to providing a free function would go like this:

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

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

You can see where this is going...

枉心 2024-12-23 23:22:51

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

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

您可以使用带有静态方法的类来包装它,并且如果需要的话,可以是静态成员。

A simple wrapper function looks like:

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

If you want to be able to pass the parameters to the functor itself, the simplest way is to sneak them in using (brr) a global variable:

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

You can wrap it with a class with a static method and a static member if you want.

无言温柔 2024-12-23 23:22:51

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

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

Here's one compile-time solution. Depending on what you need, this might be a too limited solution for you.

template<typename Func, int Param>
int wrapper(int i)
{
    static Func f(Param);
    return f(i);
}
埋葬我深情 2024-12-23 23:22:51

线程安全版本,限制是不能在线程中使用不同的参数调用遗留代码。

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

#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;
    }

A thread-safe version under the restriction that the legacy code is not called with different parameters in a thread.

IMHO, one cannot get rid of global storage.

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