Arn*_*rne 9 c++ embedded templates stm32
我目前在STM32平台上参与嵌入式C++开发.我们的团队正在评估模板的使用,以便为各种低级硬件设备参数化驱动程序.
所有有效的模板特化都是事先已知的,因此我们可以在实现文件中明确地给出所有有效的特化(实现和声明分离).事实上,对我们来说,显式专业化非常有用,因为它有助于记录可行的参数集.
// file i2c_dev.h
template<typename traits>
struct i2c_dev
{
public:
static void init();
static void send();
static bool busy();
...
private:
static i2c_transfer periodic_transfer; // class with used-defined constructor
};
// traits class for configuration A
struct i2c_dev_traitsA
{
enum
{
I2Cx_BASE = I2C1_BASE
, PORTx_BASE = GPIOB_BASE
, PORTx_PIN_TX = PB08
, PORTx_PIN_RX = PB09
};
};
// traits class for configuration B, different I2C peripherial and pinout
struct i2c_dev_traitsB
{
enum
{
I2Cx_BASE = I2C2_BASE
, PORTx_BASE = GPIOA_BASE
, PORTx_PIN_TX = PA01
, PORTx_PIN_RX = PA02
};
};
// file i2c_dev.cpp
// Implementation of template functions
template<typename traits>
void i2c_devy<traits>::init() { ... }
...
// explcitly specialize for all valid traits classes
template class i2c_dev<i2c_dev_traitsA>;
template class i2c_dev<i2c_dev_traitsB>;
Run Code Online (Sandbox Code Playgroud)
尽管通常只会实际使用其中一个特化,但是为未使用的特化生成的代码会被链接器从最终图像中删除,这正是我们想要的.
但是,periodic_transfer每个模板特化的静态成员变量(在上面的示例中)都保留在可执行文件中,这可以在arm-none-eabi-nm工具生成的内存映射中看到.这可能是因为它i2c_transfer不是POD而是具有用户定义的构造函数.删除构造函数后,将事物转换为POD类型,静态成员也会消失.
有没有办法删除显式实例化但未使用的模板的静态非POD成员?
此致,Arne
编辑#1:重新思考问题后,我提出了以下解决方案,这显然解决了问题.
i2c_transfer实际上只有为了清晰和易用而具有它的构造函数的类,其数据成员移动到POD基类中,i2c_transfer_pod如下所示:
struct i2c_transfer_pod
{
protected:
uint16_t m_size;
char* m_buffer;
};
struct i2c_transfer : public i2c_transfer_pod
{
public:
i2c_transfer();
i2c_transfer(i2c_direction_enum dir, char*buffer, uint16_t count);
bool failed();
bool succeeded();
};
Run Code Online (Sandbox Code Playgroud)
然后,未使用的特化的静态成员i2c_dev<traits>也将从最终的可执行文件中删除(如映射文件所示).
编辑#2:虽然回答一个人自我感觉有点蹩脚..我会请求对提议的解决方案发表评论.有可能更优雅的方式吗?编译器真的(正如我所假设的那样)是否优化了额外的推导?
编辑#3:我关闭了这个问题,因为解决方案适合我.能够深入了解观察到的行为的原因会很高兴.
有问题的编译器是 arm-none-eabi-gcc (Sourcery G++ Lite 2011.03-42) 4.5.2
答案(来自编辑#1):在重新思考问题之后,我提出了以下解决方案,这显然解决了问题。
当类i2c_transfer实际上拥有其构造函数只是为了清晰和易于使用时,将其数据成员移至 POD 基类中,i2c_transfer_pod如下所示:
struct i2c_transfer_pod
{
protected:
uint16_t m_size;
char* m_buffer;
};
struct i2c_transfer : public i2c_transfer_pod
{
public:
i2c_transfer();
i2c_transfer(i2c_direction_enum dir, char*buffer, uint16_t count);
bool failed();
bool succeeded();
};
Run Code Online (Sandbox Code Playgroud)
然后,未使用的专业化的静态成员i2c_dev<traits>也会从最终的可执行文件中删除(如映射文件所示)。
| 归档时间: |
|
| 查看次数: |
590 次 |
| 最近记录: |