我正在为Actor系统设计一个消息队列,其中消息队列包含std :: function对象。将消息添加到队列的客户端代码具有复杂的语法,我想简化。一些示例代码:
class Actor
{
std::deque<std::function<void()>> fMessageQueue;
template <class F, class ... Args>
void AddMessage(F &&fn, Args && ... args)
{
fMessageQueue.push_back(std::bind(std::forward<F>(fn), std::forward<Args>(args)...));
}
}
class MyActor : public Actor
{
void Behaviour1(float arg) {/*do something*/}
}
要使用上述课程,我可以这样做:
int main(int argc, const char **argv)
{
MyActor a;
a.AddMessage(&MyActor::Behaviour1, &a, 1.0f); // redundant 2nd argument &a, needed by std::bind()
}
理想情况下,我想使用以下代码语法:
int main(int argc, const char **argv)
{
MyActor a;
a.AddMessage(&MyActor::Behaviour1, 1.0f); // notice no 2nd argument &a
}
我希望客户端API不需要第二个实例&#39; a&#39; (用作std :: bind()的第二个参数)。
在搜索网络时,我设法找到了一些接近我想要实现的东西,但是参数语法是相反的:
template <class M> struct Behaviour;
template <class C, class ... Args> struct Behaviour<void(C::*)(Args ...)>
{
using M = void (C::*)(Args ...);
template <M mp> static void Call(C *target, Args && ... args)
{
target->fMessageQueue.push_back(std::bind(mp, target, args ...));
}
};
#define MSG(m) Behaviour<decltype(m)>::Call<m>
示例呼叫使用将是:
int main(int argc, char **argv)
{
MyActor a;
Actor::MSG(&MyActor::Behaviour1)(&a, 1.0f);
}
这稍微清晰一点,但仍然不太像我理想的调用语法。我也不喜欢宏观味精。最简单的API调用语法是:
a.AddMessage(&MyActor::Behaviour1, 1.0f);
有谁知道如何简化调用语法,以便客户端不必指定参数#2?