Joe*_*Joe 9 gcc templates bare-metal c++11
几年前我开始了一个裸机(Cortex-M)项目.在项目设置中,我们决定使用gcc工具链和C++ 11/C++ 14等启用,甚至使用C++异常和rtti.
我们目前正在使用来自launchpad.net/gcc-arm-embedded的gcc 4.9(有一些问题阻止我们目前更新到更新的gcc版本).
例如,我写了一个基类和这样的派生类(另请参见此处运行示例):
class OutStream {
public:
explicit OutStream() {}
virtual ~OutStream() {}
OutStream& operator << (const char* s) {
write(s, strlen(s));
return *this;
}
virtual void write(const void* buffer, size_t size) = 0;
};
class FixedMemoryStream: public OutStream {
public:
explicit FixedMemoryStream(void* memBuffer, size_t memBufferSize): memBuffer(memBuffer), memBufferSize(memBufferSize) {}
virtual ~FixedMemoryStream() {}
const void* getBuffer() const { return memBuffer; }
size_t getBufferSize() const { return memBufferSize; }
const char* getText() const { return reinterpret_cast<const char*>(memBuffer); } ///< returns content as zero terminated C-string
size_t getSize() const { return index; } ///< number of bytes really written to the buffer (max = buffersize-1)
bool isOverflow() const { return overflow; }
virtual void write(const void* buffer, size_t size) override { /* ... */ }
private:
void* memBuffer = nullptr; ///< buffer
size_t memBufferSize = 0; ///< buffer size
size_t index = 0; ///< current write index
bool overflow = false; ///< flag if we are overflown
};
Run Code Online (Sandbox Code Playgroud)
因此,我班级的客户现在可以使用例如:
char buffer[10];
FixedMemoryStream ms1(buffer, sizeof(buffer));
ms1 << "Hello World";
Run Code Online (Sandbox Code Playgroud)
现在我想让这个类的使用更加舒适,并介绍了以下模板:
template<size_t bufferSize> class FixedMemoryStreamWithBuffer: public FixedMemoryStream {
public:
explicit FixedMemoryStreamWithBuffer(): FixedMemoryStream(buffer, bufferSize) {}
private:
uint8_t buffer[bufferSize];
};
Run Code Online (Sandbox Code Playgroud)
从现在开始,我的客户可以写:
FixedMemoryStreamWithBuffer<10> ms2;
ms2 << "Hello World";
Run Code Online (Sandbox Code Playgroud)
但从现在开始,我发现可执行二进制文件的大小越来越大.似乎gcc为每个不同的模板实例化添加了符号信息FixedMemoryStreamWithBuffer
(因为我们因某种原因使用rtti).
可能有办法摆脱一些特定的类/模板/模板实例化的符号信息吗?
可以为此获得非便携式gcc解决方案.
出于某种原因,我们决定更喜欢模板而不是预处理器宏,我想避免使用预处理器解决方案.
是的,有一种方法可以将必要的符号几乎简化为0
:使用标准库。您的OutStream
课程是 的简化版本std::basic_ostream
。你OutStream::write
真是公正std::basic_ostream::write
等等。看看这里。溢出的处理确实很仔细,但为了完整起见,它还处理underflow
数据检索的需要;您可以将其保留为未定义(也是如此virtual
)。
同样,您FixedMemoryStream
有std::basic_streambuf<T>
一个固定大小的(a std::array<T>
)获取/放置区域。
因此,只需让您的类继承标准类,您就会减少二进制大小,因为您正在重用已经声明的符号。
现在,关于template<size_t bufferSize> class FixedMemoryStreamWithBuffer
. std::array<std::uint8_t, bufferSize>
这个类与指定和获取内存的方式非常相似。您无法对此进行太多优化:每个实例化都是不同的类型,并且具有所有含义。编译器无法“合并”或对它们执行任何魔法:每个实例化都必须有自己的类型。因此,要么依靠std::vector
或使用一些固定大小的专用块,例如 32、128 等,并且对于介于两者之间的任何值,都会选择正确的值;这可以完全在编译时实现,因此没有运行时成本。
归档时间: |
|
查看次数: |
984 次 |
最近记录: |