2

我为我的嵌入式 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 -> WeirdClass *,uint8_t[16] -> uint8_t *。我不能轻易地将缓冲区包装在类中,因为我以“原始”形式处理中断中的传输 - 我需要的只是指向缓冲区的指针,该指针稍后通过消息队列传递给任务进行处理,带有“类型” (大小) 作为消息的元素之一。如果可能的话,我想避免在这个简单的任务中使用虚函数 (;

可以做到吗,还是我要求太多了?也许唯一的解决方案是使模板的接口像这样:

template <typename T, size_t array_size, size_t size>

所以我有:

SimplePoolAllocator<WeirdClass, 1, 10> pool1;
SimplePoolAllocator<uint8_t, 16, 10> pool2;

但这看起来也不是很好……

提前谢谢任何建议!请注意,这个问题是关于微控制器的项目,所以使用 Boost 或类似的东西是不可能的。

4

1 回答 1

5

你应该专注于你的课程:

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);
...
};

这可能是分离这些案例并独立处理它们的最简单方法。

于 2013-10-20T08:51:48.993 回答