我编写了一个Ringbuffer类,其中包括用来缓冲数据进行串行传输的类。缓冲区的大小由模板参数BUFFER_SIZE定义。这在避免动态内存分配的同时,保持了缓冲区的通用性。例如,接收和发送缓冲区的大小可以不同,并且在编译时就知道内存的使用情况。目标是一个小型微控制器(AVR)。
Ringbuffer类的简化表示:
template<int BUFFER_SIZE>
class Ringbuffer
{
protected:
uint8_t _buffer[BUFFER_SIZE];
public:
void push(uint8_t);
uint8_t getNext();
}
使用Ringbuffer的类(例如用于框架或控制UART的类)不需要知道Ringbuffer的模板参数BUFFER_SIZE。
使用动态多态性可以很容易地实现这一点。但是,我希望避免动态多态(虚拟函数查找、缺少编译器检查)的成本。
是否有不同的方法将对模板类的访问与其模板参数分离?
与动态多态相反,使用静态多态性(使用奇怪的重复模板模式)无法解决这个问题。
微控制器的有限资源是我希望避免动态内存分配和动态多态的主要原因。
AVR的C++在某种程度上是有限的,但是答案可以忽略这一点。
发布于 2017-04-06 08:10:27
这个解决方案对你有用吗?
// Pass pointer to `Ringbuffer` to use in other classes
class Ringbuffer
{
uint8_t* _bufPtr; // Downside is you need to store additional 2 fields
int _bufSize;
protected:
constexpr Ringbuffer(uint8_t* bufPtr, int bufSize) : _bufPtr(bufPtr), _bufSize(bufSize) { }
template <std::size_t N>
constexpr Ringbuffer(uint8_t (&buffer)[N]) : _bufPtr(buffer), _bufSize(N) {}
constexpr Ringbuffer(const Ringbuffer&) = default;
Ringbuffer& operator=(const Ringbuffer&) = default;
public:
void push(uint8_t); // Work with _bufPtr / _bufSize instead of _buffer
uint8_t getNext();
};
// Passed pointers to `Ringbuffer` will actually point to `RingbufferFinal`
// with static buffer with parametrized size
template<int BUFFER_SIZE>
class RingbufferFinal : public Ringbuffer
{
protected:
uint8_t _buffer[BUFFER_SIZE];
public:
constexpr RingbufferFinal() : Ringbuffer(_buffer) {}
constexpr RingbufferFinal(const RingbufferFinal<BUFFER_SIZE>& other) :
Ringbuffer(*this)
{
// Copy contents of other._buffer only.
// _bufPtr of both buffers remains unchanged.
memcpy(_buffer, other._buffer, BUFFER_SIZE);
}
constexpr RingbufferFinal& operator=(const RingbufferFinal<BUFFER_SIZE>& other)
{
memcpy(_buffer, other._buffer, BUFFER_SIZE);
return *this;
}
};
编辑:正如Jarod42所指出的,以前的解决方案在复制时失败了,因此我添加了复制函数以确保正确性。在这种情况下,我想在缓冲区之间复制内容是正确的行为,不应该允许复制基类。
https://stackoverflow.com/questions/43259414
复制相似问题