C++ 下 typeof 的實現


現在我們有這樣一坨代碼:

C++11下有typeof和auto關鍵字,於是像上面第3行那樣糾結的位置可以變得簡單不少:

假如有typeof的話,auto可以很簡單的模擬出來,那么問題的關鍵點在於如何實現typeof。


一、需要注冊id的typeof

在C++里,可以在編譯期計算表達式類型的只有下面兩個東西:

1. sizeof
    這東西很強大,不論后面的表達式是什么,均可以在編譯期正確得到類型並直接返回類型大小。
2. typeid
    若不使用C++的RTTI功能,typeid會在編譯期計算出表達式的類型,並返回一個type_info引用。

使用第一種方法,我們可以得到一個數字,只要這個數字對類型而言是唯一的,那么我們就可以通過它反向得到類型。
類似這樣寫:

第6-9行定義了假函數encode,負責把__VA_ARGS__的類型取出來。sizeof運算符保證了encode並不會真正被執行到。

為了讓我們前面的代碼可以工作,還需要使用模板特化的機制注冊一些類型:


二、自動分配id的typeof

目前我們實現的type_of雖然可以工作,但在干活之前必須要先注冊一大堆類型,而且還需要給每個類型分配一個唯一的id。沒有注冊的類型是無法動態推導的。
boost里使用了mpl庫里的一些東西,完成了REGISTER_TYPE的過程,自動化的給每個放入BOOST_TYPE_OF里的類型分配了唯一的id。我們手頭上沒有這么NX的東西,只好使用一些輕量級的玩意了。

比如上面提到的typeid,就是個不錯的id生成器,也具有sizeof類似的功能。
雖然多態類繼承的情況會讓typeid在編譯期失效,但只限於傳入對象的情況。我們可以使用指針規避這個問題,typeid將在編譯期返回一個指針類型的type_info。

下面我們開始實作可以自動分配id的typeof。首先,我們需要一個可以把type_info&變成類型的玩意:

最后把類型解出來:

使用Encode、Decode的目的,是為了繞過typeid對對象可能進行的運行時處理。

不要妄想C++的模板自動推導可以這樣寫:

為了讓Extract能夠認得傳入的類型信息,我們得注冊我們的類型,但是不再需要傳入id了:


三、全自動的typeof

雖然僅僅寫一行REGISTER_TYPE已經不是什么大問題了,但多寫這一行還是一個讓人不爽的事情。
想要實現全自動注冊,得解決一個麻煩的問題:如何通過const type_info&特化模板?

幸好vc里還有一些小花招可以利用,我們可以嘗試在一個類的內部特化一個類模板:

這樣我們就可以寫出一個專門用於注冊的類模板:

[cpp]  view plain copy
 
  1. /* 
  2.     Register a type 
  3. */  
  4.   
  5. template<typename T, typename ID>  
  6. struct Register : Extract<ID, T>  
  7. {  
  8.     typedef typename id2type<true>::type_t type_t;  
  9. };  


它將通過繼承的Extract自動特化出一個存有類型信息的id2type。

后面的事情就簡單了,只需要稍微改寫一下Encode:

掃尾工作:

區別對待vc和gcc,並定義auto:


相關內容請參考:

http://svn.boost.org/svn/boost/trunk/boost/typeof/msvc/typeof_impl.hpp

文章代碼請參考:

http://neonx.googlecode.com/svn/trunk/neoncore/type/typeof.h

更多內容請訪問:

http://darkc.at

http://blog.csdn.net/markl22222/article/details/10474591


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM