5

我厌倦了 pass-callback-data-as-void*-struct 反模式。Boost bind 很好地解决了它,但它是一个不可接受的依赖项。什么是轻量级的替代品?我将如何尽可能简单地自己编写它?

4

7 回答 7

17

首先,我质疑你的说法,即它对你来说太重了,无法使用。

其次,如果您需要控制行为,请滚动您自己的模板。

第三,如果你害怕滚动自己的模板,我怀疑你判断它boost::bind太重而无法使用的能力。

于 2008-12-19T16:21:06.957 回答
7

查看 Don Clugston 的快速代表。据说它是您在大多数当前平台上可以找到的最快的委托(编译成 2 条汇编指令。) 1.4+ 版获得了一些 Boost.Bind 兼容性。

于 2008-12-19T19:54:46.977 回答
2

我不熟悉 boost:bind,但它是这样的吗?

#include <iostream>

void foo (int const& x) {
    std::cout << "x = " << x << std::endl;
}

void bar (std::string const& s) {
    std::cout << "s = " << s << std::endl;
}

template<class T>
void relay (void (*f)(T const&), T const& a) {
    f(a);
}

int main (int argc, char *argv[])
{
    std::string msg("Hello World!");
    relay (foo, 1138);
    relay (bar, msg);
}

输出 -

x = 1138
s = Hello World!
于 2008-12-19T16:13:29.343 回答
2

一个常见的 C++ 习惯用法是使用函子(即覆盖 operator() 的对象)。关键是您使用单个对象来封装要回调的代码以及该代码将作用于的数据。仿函数是手动滚动的,还是使用 boost::bind 和/或 <functional> 生成的,可能不会对运行时开销产生很大影响。

所以而不是:

typedef void (*cb)(void*);
void funcThatNeedsCallback(cb thecallback, void *thedata) {
    // blah blah
    thecallback(thedata);
}

做:

template<typename T>
void funcThatNeedsCallback(T &thefunctor) {
    // blah blah
    thefunctor();
}

然后调用者执行:

struct MyFunctor {
    int mydata1;
    char *mydata2;
    void operator()(void) {
        // do something with mydata1 and mydata2
    }
};

MyFunctor mf = { value1, value2 };
funcThatNeedsCallback(mf);

显然,如果您愿意,可以将成员设为私有并将它们传递给构造函数,而不是使用初始化列表。

如果您担心模板(例如,如果 funcThatNeedsCallback 是很多重复的代码),那么使用抽象类来定义参数必须具有的虚拟方法,并将该方法用作回调:

class CallbackInterface {
    virtual void theCallback(void) = 0;
    virtual ~CallbackInterface() {} // just in case
};

void funcThatNeedsCallback(CallbackInterface &cb) {
    // blah blah
    cb.theCallback();
}
于 2008-12-19T16:16:18.947 回答
2

当与 boost::bind 一起使用时,Boost.Function 在 1.34 左右显着提高了性能。如果您使用旧的 bo​​ost 版本进行了配置,则可以使用更新的版本再次进行配置。boost::function能够将小函数对象保存在堆栈上分配的小缓冲区中,而不是堆上(使用放置新)。

请参阅此邮件列表消息: http: //lists.boost.org/Archives/boost/2006/01/98993.php

于 2008-12-19T18:26:33.550 回答
1

libsigc++。许可证是 LGPL,但实现是关于 Boost.Signal 的作用(我正在阅读“太重量级”的意思是“安装所有 Boost 太重量级”而不是“Boost.Signal 太慢”)。

于 2008-12-19T20:44:12.667 回答
1

捍卫 boost::binds 速度的人可能从未编写过低延迟交易系统或高速图形库。
Boost 是一个很好的通用库,而不是速度优化的库。相比之下,一些 boost 库(与调整后的实现相比)可能相当慢。

对于函数/委托,请参阅http://www.codeproject.com/KB/cpp/fastdelegate2.aspx以获得有用的比较。

再见。

于 2010-01-22T10:50:46.927 回答