我在一个内存受限的嵌入式环境中工作,在该环境中,malloc/free new/delete 是不可取的,我正在尝试使用 std::function 模式来注册回调。我无法访问我的目标代码中的任何 STL 方法,因此我很不幸,不得不自己复制一些 STL 功能。由于调用者需要进行捕获,函数指针对我来说不是一个选项。
例如,我想声明一个可以注册 onChange 事件的 Mailbox 类
class Mailbox {
std::function<void(int,int)> onChange;
};
这样,调用者就可以注册一个 lambda onChange
处理程序,它可以捕获这个或其他对处理事件很重要的变量。
由于这是 API 的一部分,我想为 Mailbox 的用户提供最大的灵 active ,以提供函数指针、lambda 或仿函数。
我设法找到了 great implementation std::function
的开销看起来特别低,除了涉及动态内存外,它完全符合我的需要。
如果你看下面的代码,动态内存只用在一个地方,而且它似乎完全限定在被模板化的对象范围内,这表明它的大小应该在编译时就知道。
谁能帮我理解如何重构此实现,使其完全静态并删除对 new/malloc 的使用?我无法理解为什么在编译时无法计算 CallableT 的大小。
下面的代码(不适合胆小的人)。请注意,它使用 make_unique
/unique_ptr
但这些可以很容易地替换为 new 和 * 并且我已经成功测试了该用例。
#include <iostream>
#include <memory>
#include <cassert>
using namespace std;
template <typename T>
class naive_function;
template <typename ReturnValue, typename... Args>
class naive_function<ReturnValue(Args...)> {
public:
template <typename T>
naive_function& operator=(T t) {
callable_ = std::make_unique<CallableT<T>>(t);
return *this;
}
ReturnValue operator()(Args... args) const {
assert(callable_);
return callable_->Invoke(args...);
}
private:
class ICallable {
public:
virtual ~ICallable() = default;
virtual ReturnValue Invoke(Args...) = 0;
};
template <typename T>
class CallableT : public ICallable {
public:
CallableT(const T& t)
: t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return t_(args...);
}
private:
T t_;
};
std::unique_ptr<ICallable> callable_;
};
void func() {
cout << "func" << endl;
}
struct functor {
void operator()() {
cout << "functor" << endl;
}
};
int main() {
naive_function<void()> f;
f = func;
f();
f = functor();
f();
f = []() { cout << "lambda" << endl; };
f();
}
编辑:添加了对 STL 的说明
最佳答案
您要查找的名称是“in-place function
”。现在至少有一个非常好的实现:
还有 tj::inplace_any<Size, Align>
, 如果你需要/想要 any
的语义.
关于c++ - std::c++ 静态分配函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45088723/