我为我的嵌入式MCU项目做了一个非常简单的池分配器。这是一个带有以下界面的模板类(跳过实现部分,如果有人有兴趣,我也可以发布它):
template <typename T, size_t size>
class SimplePoolAllocator
{
public:
SimplePoolAllocator();
T * allocate();
void deallocate(T *pointer);
...
}
它非常适用于类或POD等“简单”事物,例如:
SimplePoolAllocator<double, 10> poolOfDouble; // returns "double *"
SimplePoolAllocator<WeirdClass, 5> poolOfObjects; // returns "WeirdClass *"
如果我想将它用于固定大小的数组,则会出现问题。这个用途当然是原始数据缓冲区 - 在我的项目中我有两个“传输”类型,一个有16个字节,另一个有100个。
所以假设我使用这样的话:
SimplePoolAllocator<uint8_t[16], 10> pool1;
SimplePoolAllocator<uint8_t[100], 10> pool2;
一切似乎都很好,但问题是现在allocate()返回类似于:“uint8_t(*)[16]”和“uint8_t(*)[100]”。理想情况下,我希望在这种情况下只返回“uint8_t *”(指向开头)。
我知道我可以这样做:
uint8_t *p = *pool1.allocate(); // additional asterisk to "drop" the array thing from the type
但这看起来......很奇怪......
所以问题是 - 如何改进我的SimplePoolAllocator接口(或任何东西)以支持简单分配“普通”对象(如上所示 - 类和POD)和固定大小的数组,但只返回指向第一个的指针元件?可以不使用std :: array并使用它的data()成员函数,或者没有额外的'*'来完成它吗? C ++ 11的功能对我来说还可以,如果会有“转换”这样的类型,它可以在这里保存我:WeirdClass - &gt; WeirdClass *,uint8_t [16] - &gt; uint8_t *。我无法轻松地将缓冲区包装在类中,因为我以“原始”形式处理中断传输 - 我需要的是指向缓冲区的指针,稍后通过消息队列传递给任务进行处理,使用“type”( size)作为消息的一个要素。如果可能的话,我想避免使用虚函数来完成这个简单的任务(;
它可以完成,或者我可能要求太多了?也许唯一的解决方案是使模板的接口像这样:
template <typename T, size_t array_size, size_t size>
所以我有:
SimplePoolAllocator<WeirdClass, 1, 10> pool1;
SimplePoolAllocator<uint8_t, 16, 10> pool2;
但这看起来也不太好......
提前thx任何建议!请注意,这个问题是关于微控制器的一个项目,所以使用Boost或类似的东西是不可能的。答案 0 :(得分:4)
你应该专攻你的课程:
template <typename T, size_t size>
class SimplePoolAllocator
{
public:
SimplePoolAllocator();
T * allocate();
void deallocate(T *pointer);
...
};
template <typename T, size_t N, size_t size>
class SimplePoolAllocator<T[N],size> // <-- here
{
public:
SimplePoolAllocator();
// you can now use different signatures and different implementations:
T ** allocate();
void deallocate(T **pointer);
...
};
这可能是分离这些案件并独立对待它们的最简单方法。