我目前參與的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>;
雖然一般只將實際使用的特例之一,未使用的專業化生成的代碼被鏈接器,這正是我們想要的東西從最終圖像去除。
但是,每個模板專業化的靜態成員變量 - periodic_transfer
保留在可執行文件中,如arm-none-eabi-nm
工具生成的存儲器映射中所示。這可能是由於i2c_transfer
不是POD,但具有用戶定義的構造函數。當構造函數被刪除時,把它變成POD類型,靜態成員也會消失。
有沒有辦法去除的顯式實例化靜態非POD成員,但未被使用的模板?
問候, 阿恩
編輯#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();
};
然後,未使用的i2c_dev<traits>
的靜態成員專業化也從最終的可執行文件中移除(如地圖文件所示)。
編輯#2:雖然回答一個自我感覺有點跛。我謹請上提出的解決方案的意見。有沒有更優雅的方式?編譯器是否真的(正如我所想的那樣)優化了額外的派生?
編輯#3:我關閉問題,因爲該解決方案爲我工作。如果能夠更深入地瞭解觀察到的行爲的原因,那將是很好的。
有問題的編譯器是arm-none-eabi-gcc (Sourcery G++ Lite 2011.03-42) 4.5.2
如果你找到了解決你的問題,你應該張貼它作爲一個答案。 – 2012-01-17 19:04:42
聽起來像一個奇怪的編譯器嘀嗒,因爲根本不應該有任何區別,恕我直言。 – Xeo 2012-01-17 19:15:07
什麼版本是什麼版本? – 2012-01-17 19:55:25