如何为具有不同签名的函数分配相同的签名?

时间:2012-08-23 21:05:54

标签: c++ function pointers boost functor

在我的C ++应用程序中,我有2个线程:(i)主线程,(ii)后台线程。 我有一个类定义为:

class helper
{
 public:
     bool login(const string& username, const string& password);
     void logout();

 private:
     bool loginInternal(const string& username, const string& password);
     void logoutInternal();
}
在主线程上调用

helper :: login()和helper :: logout()函数(以及具有各种返回类型和#spams和param类型的其他几个成员函数)。在这些函数的实现中,相应的内部函数将在队列中排队,后台线程按照它们排队的顺序调用这些内部函数。所以像这样:

bool helper::login(const string& username, const string& password)
{
    queue.push_back(boost::bind(&helper::loginInternal, this, username, password));
}

void helper::logout()
{
    queue.push_back(boost::bind(&helper::logoutInternal, this));
}

所有这一次后台线程都在运行,等待队列填满,一旦这样做,这个后台线程就会开始调用队列中的函数:

queue.front()();
queue.pop_front();

所以问题是,我该如何定义这样的队列?

deque<???> queue;

这个队列的数据类型是什么,它可以在同一队列中保存具有不同签名的回调函数?

编辑: 这是解决方案(感谢J. Calleja):

typedef boost::function<void ()> Command;
deque<Command> queue;

然后像这样调用仿函数:

// Execute the command at the front
Command cmd = queue.front();
cmd();

// remove the executed command from the queue
queue.pop_front();

2 个答案:

答案 0 :(得分:1)

如果您规范化返回类型或忽略它,则可以使用boost::function。该库定义了一个包装器,可以存储与您的签名(函数或函子)匹配的任何元素。

使用您的示例:

#include <boost/function.hpp>

class helper 
{  
public:      
  bool login(const std::string& username, const std::string& password);
  void logout();
private:      
  bool loginInternal(const std::string& username, const std::string& password);
  void logoutInternal();
private:
  typedef boost::function<void ()> Command;
  std::deque<Command> queue;
};

此示例忽略返回类型,因为它声明返回void的函数。如果您想知道返回值,则必须使logout返回bool并将声明更改为:

  typedef boost::function<bool ()> Command;

答案 1 :(得分:0)

我认为第一个的类型是bind<bool>,第二个的类型是bind<void>。由于这些是两种不同的类型,因此您无法将它们放入一个队列中。让logout返回bool(即使它始终返回true或其他内容)将是解决此问题的一种方法(可能相对无痛)。

tl; dr:更改logout以返回bool,然后将您的队列声明为deque< bind<bool> >

编辑:考虑到很多类型,我建议你为自己创建一些特殊的容器类。像这样:

class EnqueuedFunc
{
    virtual void operator()() = 0;
};

class LoginFunc : public EnqueuedFunc
{
    bind<bool> func;

    LoginFunc(bind<bool> fn)
    {
        func = fn;
    }
    void operator()()
    {
        fn();
    }
};

class LogoutFunc : public EnqueuedFunc
{
    bind<void> func;

    LoginFunc(bind<void> fn)
    {
        func = fn;
    }
    void operator()()
    {
        fn();
    }
};

然后您的队列为deque<EnqueuedFunc>