C++0x: auto 和 decltype


在上一篇的《C++ 語法再加強:C++0x》中,有列出在 Visual C++ 2010 中所新增的六項 C++0x Core Language 的新功能,也大概針對了各項也做了極為簡單的說明;而這一篇,就先來講 autodecltype 這兩項新功能吧~

auto keyword

首先,auto 這個 ketword 其實在 VC++2010 前是有其他用處的;他是所謂的「storage-class specifier」,是用來告訴編譯器一個物件或函式的週期和可見範圍、同時也告訴編譯器他應該如何被儲存。而這一類的 specifier 包括了 autoexternmutableregisterstatic 這五種,不過由於這不是本文的重點,所以就不多花時間說明了。

在 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 的變數。而如果把 autodecltype 這個 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 一樣是 intb

decltype 最主要的用處,是用來和 auto 一起使用,來簡化 template 函式的開發。


auto + decltype

前面一直有提到,當把 autodecltype 合併使用時,可以用來簡化部分的 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 函式,用來套用在不同的狀況下~像以下方的例子來說,由於 TU 相加可能會產生不同的型別,而本來的寫法會需要考慮到這個需要回傳的型別;但是使用 autodecltype 的話,就可以讓編譯器自己去判斷要回傳的型別了~

template<typename T, typename U>
auto myFunc( T& t, U& u)-> decltype( t + u ){
  return t + u;
}; 

不過說實話,Heresy 自己也還不知道這樣的功能可以用在什麼地方?本來剛看到的時候是有想到一些地方可能可以用上,但是實際玩了一下卻都發現會踩到一些限制而無法使用,總覺得似乎沒想像中的方便?不過也或許是還沒碰到需要、符合這種功能的例子吧?


參考資料:

Advertisements

關於 Heresy
https://kheresy.wordpress.com

15 Responses to C++0x: auto 和 decltype

  1. 通告: C++14 進行中,來看目前的委員會草案吧~ | Heresy's Space

  2. 通告: C++0x:static_assert 和 nullptr « Heresy's Space

  3. 通告: C++0x:Lambda expression « Heresy's Space

  4. cmchao says:

    請教個小問題,在最後一例,如果你的template function 有multi-return path 的話,依然可以用嗎?

    喜歡

    • Heresy says:

      他這邊只是透過 t + u 來判斷回傳值的型別啊。
      基本上 multi-return path 對於 decltype 的判斷結果並不會有影響。

      喜歡

  5. Kun-Yi says:

    auto 看起來對寫code的來說爽, 對後來維護的人是一種痛

    喜歡

    • Heresy says:

      看怎麼用啦~
      Heresy 是覺得如果用在比較小的 block 裡面,再加上良好的命名的話,應該不至於會對程式解讀造成妨礙。

      喜歡

      • Kun-Yi says:

        但是這要有良好的習慣 我想有這種習慣的在台灣不是多數 :P

        喜歡

        • Heresy says:

          XD 沒關係,會的人可能也不多
          (總覺得現在寫 C/C++ 的人好少…

          喜歡

          • Kun-Yi says:

            寫C的還蠻多的 寫C++ 的很少, C++ 真的用的好, 要很深的功力 我已經放棄繼續用C++很久了 :P 而且看別人寫的code 真的不好分出先後, 做 WinCE Driver 時就被搞過 T_T

            喜歡

          • Heresy says:

            C++ 很方便啊! XD

            喜歡

          • Kun-Yi says:

            方便是對熟悉的framework 而言吧! 不熟悉的要花很多時間追code 先熟悉 framwork or class, C很直觀不用花這種預學習的時間

            喜歡

          • Heresy says:

            XD 很久沒有看純 C 的東西了。
            現在寫都會想包成 class

            喜歡

  6. 通告: C++ 語法再加強:C++0x « Heresy's Space

  7. 通告: C++11 標準正式發布! « Heresy's Space

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

%d 位部落客按了讚: