我在一个内存受限的嵌入式环境中工作,其中malloc/free new/delete是不可取的,我正在尝试使用std :: function模式来注册回调.我无法访问目标代码中的任何STL方法,因此我不得不自己复制一些STL功能.函数指针对我来说不是一个选项,因为调用者必须有捕获.
例如,我希望声明一个类邮箱,其中可以注册onChange事件
class Mailbox {
std::function<void(int,int)> onChange;
};
Run Code Online (Sandbox Code Playgroud)
这样,调用者可以注册一个lambda onChange处理程序,它可以捕获这个或其他对处理事件很重要的变量.
由于这是API的一部分,我想为Mailbox的用户提供最大的灵活性,以提供函数指针,lambda或functor.
我已经设法找到一个看起来特别低开销的一个很好的实现,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() = …Run Code Online (Sandbox Code Playgroud) 我想只允许在我的代码库中使用std :: function,如果它不进行任何分配.
为此我可以编写类似下面的函数的东西,只用它来创建我的函数实例:
template< typename Functor>
std::function<Functor> makeFunction( Functor f)
{
return std::function<Functor>(std::allocator_arg, DummyAllocator(), f);
}
Run Code Online (Sandbox Code Playgroud)
如果DummyAllocator在运行时被使用,它将断言或抛出.
理想情况下,我想在编译时捕获分配用例.
即
template< typename Functor>
std::function<Functor> makeFunction( Functor f)
{
static_assert( size needed for function to wrap f < space available in function,
"error - function will need to allocate memory");
return std::function<Functor>(f);
}
Run Code Online (Sandbox Code Playgroud)
这样的事情可能吗?