4

我有一个 http 服务器,它有一个这样的请求处理程序:

bool handleRequest(const RequestObject& request, ResponseRequest& response);

我正在尝试编写一个提供类似 API 的包装器:

addRouteHandler(GET, "/foo/bar", handler);

可以handler是:

  1. 一个功能:bool handleFooBarRequest(const RequestObject& request, ResponseRequest& response);
  2. 现有对象的方法:FooResourceInstance+bool FooResource::handleFooBarRequest(const RequestObject& request, ResponseRequest& response);
  3. 对象的静态方法:static bool FooResource::handleFooBarRequest(const RequestObject& request, ResponseRequest& response);

我坚持:C++03(gcc 4.1.2)并且没有Boost(原因不是重点)

到目前为止,我发现的技术要么使用 Boost、C++11 或第三方代码(http://www.codeproject.com/Articles/136799/Lightweight-Generic-C-Callbacks-or-Yet-Another-Del )

4

2 回答 2

3

使用接口和派生的模板类。这种技术称为“类型擦除”。

class CallbackBase
{
public:
    virtual ~CallbackBase() = 0;
    virtual bool exec(const RequestObject& request, ResponseRequest& response) = 0;
};

template <typename F>
class CallbackImpl : public CallbackBase
{
public:
    CallbackImpl(F f) : f_(f) {}
    virtual bool exec(const RequestObject& request, ResponseRequest& response) {
        return f_(request, response);
    }
private:
    F f_;
};

template <typename F>
void CreateCallback(F f, std::auto_ptr<CallbackBase>& r) {
    r.reset(new CallbackImpl<F>(f));
}

// examples
std::auto_ptr<CallbackBase> my_callback;

CreateCallback(GlobalFooBarRequest, my_callback);
CreateCallback(&FooResource::staticFooBarRequest, my_callback);
// for member function, use std::mem_fun and std::bind1st
...

my_callback->exec(request, response);

您可能想要使用 shared_ptr 或类似的而不是 auto_ptr,这一切都取决于您希望如何存储这些对象。

编辑:您可以编写自己的成员函数包装器/闭包/函数对象。代码如下所示(我没有尝试编译它,所以可能会出现一些错误):

template <typename T>
class RequestWrapper
{
    typedef bool (T::*F)(const RequestObject&, ResponseRequest&);
    T* obj_;
    F f_;
public:
    RequestWrapper(T* obj, F f)
    : obj_(obj)
    , f_(f)
    {}

    bool operator()(const RequestObject& request, ResponseRequest& response) const {
        return (obj_->*f_)(request, response);
    }
};

template <typename T, typename F>
RequestWrapper<T> BindRequestMfn(T* obj, F mfn)
{
    return RequestWrapper<T>(obj, mfn);
}


CreateCallback(BindRequestMfn(foo, &FooResource::fooBarRequest), my_callback);
于 2013-02-01T10:04:19.437 回答
1

此处描述的此解决方案完全有效: http: //www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates

只有3个标题。

C++03,gcc 4.1.2 OK,没有 Boost ;麻省理工学院执照

于 2013-02-04T12:29:31.273 回答