C++ 中固定大小数组的池分配器

Fre*_*pin 2 c++ arrays templates allocation c++11

我为我的嵌入式 MCU 项目做了一个非常简单的池分配器。这是一个模板化的类,接口如下(实现部分略过,有兴趣的我也可以贴出来):

template <typename T, size_t size>
class SimplePoolAllocator
{
public:
    SimplePoolAllocator();
    T * allocate();
    void deallocate(T *pointer);
...
}
Run Code Online (Sandbox Code Playgroud)

它非常适用于“简单”的东西,比如类或 POD,例如:

SimplePoolAllocator<double, 10> poolOfDouble; // returns "double *"
SimplePoolAllocator<WeirdClass, 5> poolOfObjects; // returns "WeirdClass *"
Run Code Online (Sandbox Code Playgroud)

如果我想将它用于固定大小的数组,就会出现问题。这种用途当然用于原始数据缓冲区 - 在我的项目中,我有两种“传输”类型,一种有 16 个字节,另一种有 100 个。

所以假设我像这样使用某事:

SimplePoolAllocator<uint8_t[16], 10> pool1;
SimplePoolAllocator<uint8_t[100], 10> pool2;
Run Code Online (Sandbox Code Playgroud)

一切看起来都很好,但问题是现在allocate() 返回这样的东西:“uint8_t(*)[16]”和“uint8_t(*)[100]”。理想情况下,我希望它在这种情况下只返回“uint8_t *”(指向开头的指针)。

我知道我可以这样做:

uint8_t *p = *pool1.allocate(); // additional asterisk to "drop" the array thing from the type
Run Code Online (Sandbox Code Playgroud)

但这看起来……很奇怪……

所以问题是 - 我怎样才能改进我的 SimplePoolAllocator 的接口(或任何东西)来支持“普通”对象(如上所示 - 类和 POD)和固定大小数组的简单分配,但只返回指向第一个元素的指针?可以在不使用 std::array 并使用它的 data() 成员函数的情况下完成吗,或者到处都没有额外的“*”?C++11 特性对我来说没问题,如果有什么可以“转换”这样的类型,它可以把我保存在这里:WeirdClass -> WeirdClass *, uint8_t[16] -> uint8_t *。我无法轻松地将缓冲区包装在类中,因为我以“原始”形式处理中断中的传输 - 我需要的只是指向缓冲区的指针,该指针稍后通过消息队列传递给任务进行处理,带有“类型” (size) 作为消息的元素之一。如果可能的话,我想避免在这个简单的任务中使用虚函数(;

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

template <typename T, size_t array_size, size_t size>
Run Code Online (Sandbox Code Playgroud)

所以我有:

SimplePoolAllocator<WeirdClass, 1, 10> pool1;
SimplePoolAllocator<uint8_t, 16, 10> pool2;
Run Code Online (Sandbox Code Playgroud)

但这也看起来不太好......

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

Dan*_*rey 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);
...
};
Run Code Online (Sandbox Code Playgroud)

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