在上一篇的《C++ 語法再加強:C++0x》中,有列出在 Visual C++ 2010 中所新增的六項 C++0x Core Language 的新功能,也大概針對了各項也做了極為簡單的說明;而這一篇,就先來講 auto 和 decltype 這兩項新功能吧~
auto keyword
首先,auto 這個 ketword 其實在 VC++2010 前是有其他用處的;他是所謂的「storage-class specifier」,是用來告訴編譯器一個物件或函式的週期和可見範圍、同時也告訴編譯器他應該如何被儲存。而這一類的 specifier 包括了 auto、extern、mutable、register、static 這五種,不過由於這不是本文的重點,所以就不多花時間說明了。
在 C++0x 裡,auto 這個 keyword,是用來取代直接用特定的型別(type)來宣告變數,而變數的型別則會根據所給的 initialization expression 來推導;它的形式是:
auto declarator initializer;
最簡單的例子大概如下:
int j = 0; // j is explicitly type int. auto k = 0; // k is implicitly type int.
上面這樣的程式,由於 0 是一個整數,所以用 auto 宣告的變數 k 的型別也會和 j 一樣、是 int。
而使用 auto 的好處呢?他主要的優點是可以讓複雜的類別有更簡單的宣告方法;尤其像有使用 template 時,要宣告變數往往要打很長一串,現在用 auto 可以代替這一長串的型別。例如下面的例子,兩行的寫法是等價的,但是用 auto 的話程式會簡短許多。
map<int,list<string>>::iterator i = m.begin(); auto i = m.begin();
同時,auto 也可以用來宣告變數、以儲存 lambda expression 這種匿名函式(anonymous function),或是用來宣告一個 function pointer 的變數。而如果把 auto 和 decltype 這個 type specifier 一起使用的話,還可以用來簡化 template 函式的開發。
不過在使用 auto 時, 需要注意到的是,由於他是根據 initialization expression 來判斷型別,所以和一般的變數宣告還是有些不同;下面是一些要注意的:
-
使用時一定要有 initializer,下面是簡單的例子:
auto x = 10; // ok auto x; // error! without initializer
-
auto 不能用來宣告陣列、也不能用來宣告變數的 return type、函式或 template 的參數。例如下面幾個例子都是錯誤的使用方式:
auto a[5]; auto f(){}; void f(auto j){}; template<auto T> class C{}; vector<auto> c;
這邊只是稍微列舉一些,而在 MSDN Library 的《auto Keyword (Type Deduction) 》一文中的「Restrictions and Error Messages」部分,有以可能的編譯錯誤為導向列出的完整列表,有興趣的可以參考看看。
decltype Type Specifier
decltype 這個 type specifier 是用來根據所給的 expression 決定型別,它的形式是:
decltype( expression )
他最簡單的例子,應該就是類似下面這樣的程式:
int a;
decltype( a ) b;
如此,可以宣告出一個型別和 a 一樣是 int 的 b。
而 decltype 最主要的用處,是用來和 auto 一起使用,來簡化 template 函式的開發。
auto + decltype
前面一直有提到,當把 auto 和 decltype 合併使用時,可以用來簡化部分的 template 函式的撰寫。而在實作上,這是使用名為「trailing-return-type」(或稱「late-specified return type」)的特殊函示宣告方法來做到的~下面是這種用法的基本形式:
auto function_name( parameters ) −> decltype( expression )
{
function_body;
}
這邊的 return type 是 auto、同時在 function name 後面又加上了「-> decltype( expression )」,這是透過 decltype 做判斷,告訴編譯器 auto 的型別到底是什麼;這種用來指定 retrun type 的寫法,和在使用 lambda expression 時是類似的。
這樣的寫法有什麼好處呢?透過這樣的機制,程式開發者可以寫出更有彈性的 template 函式,用來套用在不同的狀況下~像以下方的例子來說,由於 T 和 U 相加可能會產生不同的型別,而本來的寫法會需要考慮到這個需要回傳的型別;但是使用 auto 加 decltype 的話,就可以讓編譯器自己去判斷要回傳的型別了~
template<typename T, typename U> auto myFunc( T& t, U& u)-> decltype( t + u ){ return t + u; };
不過說實話,Heresy 自己也還不知道這樣的功能可以用在什麼地方?本來剛看到的時候是有想到一些地方可能可以用上,但是實際玩了一下卻都發現會踩到一些限制而無法使用,總覺得似乎沒想像中的方便?不過也或許是還沒碰到需要、符合這種功能的例子吧?
參考資料:
[…] std::tie(), 透過 structured binding declaration 來寫的話,是又利用了 auto […]
讚讚
[…] auto 來定義的變數 it 的型別(不過滑鼠移上去也會顯示就是了);而在按下 Ctrl […]
讚讚
[…] auto 和 lambda expression 等功能,Heresy […]
讚讚
[…] C++0x 的 auto、decltype 和 Lambda expression 了~而這一篇,則是繼續介紹一下 static_assert 和 nullptr […]
讚讚
[…] lambda expression 會產生類似 function obejct 的物件,所以其實我們可以用 auto(參考)或是 tr1 的 function(參考)來把 lambda expression […]
讚讚
請教個小問題,在最後一例,如果你的template function 有multi-return path 的話,依然可以用嗎?
讚讚
他這邊只是透過 t + u 來判斷回傳值的型別啊。
基本上 multi-return path 對於 decltype 的判斷結果並不會有影響。
讚讚
auto 看起來對寫code的來說爽, 對後來維護的人是一種痛
讚讚
看怎麼用啦~
Heresy 是覺得如果用在比較小的 block 裡面,再加上良好的命名的話,應該不至於會對程式解讀造成妨礙。
讚讚
但是這要有良好的習慣 我想有這種習慣的在台灣不是多數 :P
讚讚
XD 沒關係,會的人可能也不多
(總覺得現在寫 C/C++ 的人好少…
讚讚
寫C的還蠻多的 寫C++ 的很少, C++ 真的用的好, 要很深的功力 我已經放棄繼續用C++很久了 :P 而且看別人寫的code 真的不好分出先後, 做 WinCE Driver 時就被搞過 T_T
讚讚
C++ 很方便啊! XD
讚讚
方便是對熟悉的framework 而言吧! 不熟悉的要花很多時間追code 先熟悉 framwork or class, C很直觀不用花這種預學習的時間
讚讚
XD 很久沒有看純 C 的東西了。
現在寫都會想包成 class
讚讚
[…] auto:《C++0x: auto 和 decltype》[MSDN] […]
讚讚
[…] auto:《C++0x: auto 和 decltype》[MSDN] […]
讚讚