我遇到了一个问题,即在另一个线程中使用变量参数稍后调用部分限定的函数对象。
在GCC中,我一直在使用我制作的宏和typedef,但我正在完成我的项目,试图清除警告。
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
使用如下所示的Function_Cast宏会导致“警告:在指向函数的指针和指向对象的指针之间进行转换是有条件支持的”
Subscriber* init_subscriber = new Subscriber(this, Function_Cast(&BaseLoaderStaticInit::init), false);
我真正需要的是一个指针,我可以创建一个std :: bind&lt; function_type&gt;的对象。这通常是怎么做的?
此外,这种有条件支持的东西真的很烦人。我知道在x86上我的代码工作正常,我知道依赖于sizeof(void *)== sizeof(this *)的所有这些*的限制。
另外,有没有办法让clang处理像数据指针这样的函数指针,以便我的代码可以编译?我很想知道它有多糟糕(如果有的话)。
相关守则:
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
typedef void(CallTypeFunction(std::shared_ptr<void>));
Subscriber(void* owner, SubscriptionFunction* func, bool serialized = true) {
this->_owner = owner;
this->_serialized = serialized;
this->method = func;
call = std::bind(&Subscriber::_std_call, this, std::placeholders::_1);
}
void _std_call(std::shared_ptr<void> arg) { method(_owner, arg); }
答案 0 :(得分:0)
它通常是这样做的:
#include <functional>
#include <memory>
struct subscription
{
// RAII unsubscribe stuff in destructor here....
};
struct subscribable
{
subscription subscribe(std::function<void()> closure, std::weak_ptr<void> sentinel)
{
// perform the subscription
return subscription {
// some id so you can unsubscribe;
};
}
//
//
void notify_subscriber(std::function<void()> const& closure,
std::weak_ptr<void> const & sentinel)
{
if (auto locked = sentinel.lock())
{
closure();
}
}
};
答案 1 :(得分:0)
这里的问题是你试图使用成员函数指针来代替函数指针,因为你知道,在引擎盖下,它通常被实现为{{ 1}}。
function(this, ...)
但是,这并不能保证这实际上会起作用,而且很明显的情况(虚拟功能)可能会赢得它。
成员函数旨在像这样传递:
struct S {
void f() {}
};
using fn_ptr = void(*)(S*);
void call(S* s, fn_ptr fn)
{
fn(s);
delete s;
}
int main() {
call(new S, (fn_ptr)&S::f);
}
并像这样调用:
void call(S* s, void (S::*fn)())
当人们想要支持不同类型时,人们如何解决这个问题的方法是使用蹦床,这是一种非会员功能。您可以使用静态[member]函数或lambda:
执行此操作(s->*fn)();
或者如果您希望在您的呼叫站点输入安全性,那么这是一个模板化的构造函数:
auto sub = new Subscriber(this, [](auto* s){ s->init(); });
如果你的template<typename T>
Subscriber(T* t, void(T::*fn)(), bool x);
构造函数采用Subscriber
而不是函数指针,则可以传递捕获lambda并消除采用std::function<void(void))>
的需要:
void*