2013-02-03 28 views
3

我正在使用通過模板使用靜態多態的C++庫。它是這樣設計的,因爲目標是具有小堆棧的嵌入式系統,並且經常有利於成員函數節省堆棧使用。將GCC的typeof()擴展與成員訪問相結合

採用靜態多態性模板意味着該類型的事件發射器的名稱(最常見的設備驅動程序)往往令人討厭長:

class DeviceThatUsesSPI<class SPI_BUS_TYPE> { 

    public: 
    class DeviceEvent : public Event<DeviceThatUsesSPI> {}; 

    // and the rest of the device driver implementation, including 
    // the code that emits that event. 

} 

SomeSpecificGpioBus gpio_bus(); 
SoftwareSpiBus<typeof(gpio_bus)> spi_bus(&gpio_bus); 
DeviceThatUsesSPI<typeof(spi_bus)> device(&spi_bus); 

正如你所看到的,我們使用GCC typeof擴展操作符以避免重複寫出完整討厭的類型名稱​​。在我們嘗試過的每一個地方,這都像一個魅力,直到今天我試圖用它來訪問代表事件的嵌套類。在我目前的例子,這是一個模板專業化,實現編譯時的事件處理程序綁定:

typeof(device)::ExampleEvent event; 

template<> 
inline void event_handler<typeof(device)::ExampleEvent>(typeof(device) *emitter) { 
    // event handler implementation... 
} 

不過,我也是在一個變量聲明的一個更小例子,嘗試這個

在這兩種情況下,G ++都無法用語法錯誤解析表達式。我認爲這是因爲在標準C++語法中,除了標識符之外,::不會出現任何情況,解析器無法回溯並在遇到冒號時將第一部分視爲類型。

然而,the GCC manual about typeof使得這個操作如下承諾:

一個typeof結構可用於任何可使用typedef名。例如,您可以在聲明中,演員表中或sizeoftypeof中使用它。

如果我有一個typedef代替typeof兩種用法在我的例子,G ++是高興:

typedef typeof(device) device_type; 

template<> 
inline void event_handler<device_type::ExampleEvent>(typeof(device) *emitter) { 
    // event handler implementation... 
} 

device_type::ExampleEvent event; 

因此,這進一步加強了我的懷疑,編譯器是罰款與我在語義上寫的,但語法不允許我表達。儘管使用typedef間接方式確實讓我能夠使用代碼,但我更願意找到一種方法使事件處理程序聲明自成一體,以便爲此庫的用戶提供便利。有什麼方法可以編寫typeof運算符來消除解析歧義,以便我可以使事件聲明成爲一行代碼?

+0

在C++ 11中,您可以使用'decltype'而不是'typeof'這是一個編譯器擴展。 – Nawaz

+0

讓我知道我的解決方案是否有效。如果沒有,那麼我會刪除它。 – Nawaz

回答

1

我認爲一個小的元函數可以做到這一點。

template<typename T> 
struct self 
{ 
    typedef T type; 
}; 

然後用它作爲:

template<> 
inline void 
event_handler<self<typeof(device)>::type::ExampleEvent>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 

,也可以定義的元功能(這是通用)爲:

template<typename T> 
struct event 
{ 
    typedef typename T::ExampleEvent type; 
}; 

然後用它作爲:

template<> 
inline void 
event_handler<event<typeof(device)>::type>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 

順便說一句,在C++ 11,你可以用decltype代替typeof(這是一個編譯器擴展):

template<> 
inline void 
event_handler<decltype(device)::ExampleEvent>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 

希望有所幫助。 :-)

+0

那麼這意味着它的工作。大! – Nawaz

+1

啊,是的,我一開始沒有注意到你的評論。這個技巧使我可以爲GCC的老版本添加墊片,但是我也發現從GCC 4.7開始,對於typeof或decltype來說,這個技巧並不是必需的。我記錄了我在第二個答案中學到的內容,但是您的答案絕對是解決此解析器錯誤的更直接的答案。謝謝! –

2

根據a bug report against GCC這是一個已知的問題,並已爲GCC 4.7修復。升級GCC是長期的解決方案。

bug報告描述了使用類模板作爲間接繞過解析器在舊版本的另一種解決方法:

class SameType<T> { 
    public: 
    typedef T R; 
} 
T<typeof(device)>::ExampleEvent event; 

這比typedef的更好,因爲它推廣到所有事件類型,但它對用戶來說仍然不自然。

這個同樣的問題適用於新標準decltype運營商,實際上是a C++11 specification change的主題,它闡明瞭解析類型的規則,以使其按預期工作。