聲明:本文是在Alex Allain的文章http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html的基礎上寫成的。
加入了很多個人的理解,不是翻譯。
轉載請註明出處 http://blog.csdn.net/srzhz/article/details/7934483
自動類型推斷
當編譯器能夠在一個變量的聲明時候就推斷出它的類型,那麼你就能夠用auto關鍵字來作爲他們的類型:
- auto x = 1;
編譯器當然知道x是integer類型的。所以你就不用int了。接觸過泛型編程或者API編程的人大概可以猜出自動類型推斷是做什麼用的了:幫你省去大量冗長的類型聲明語句。
比如下面這個例子:
在原來的C++中,你要想使用vector的迭代器得這麼寫:
- vector<int> vec;
- vector<int>::iterator itr = vec.iterator();
- vector<int> vec;
- auto itr = vec.iterator();
比如說有這樣的代碼:
- template <typename BuiltType, typename Builder>
- void
- makeAndProcessObject (const Builder& builder)
- {
- BuiltType val = builder.makeObject();
- // do stuff with val
- }
- template <typename Builder>
- void
- makeAndProcessObject (const Builder& builder)
- {
- auto val = builder.makeObject();
- // do stuff with val
- }
因爲在得之builder的類型之後,編譯器就已經能知道makeObject的返回值類型了。所以我們能夠讓編譯器自動去推斷val的類型。這樣一來就省去了一個泛型。
你以爲自動類型推斷只有這樣的用法?那也太naive了。C++11還允許對函數的返回值進行類型推斷
新的返回值語法和類型獲取(Decltype)語句
- int temp(int a, double b);
前面那個int是函數的返回值類型,temp是函數名,int a, double b是參數列表。
現在你可以將函數返回值類型移到到參數列表之後來定義:
- auto temp(int a, double b) -> int;
後置返回值類型可以有很多用處。比如有下列的類定義:
- class Person
- {
- public:
- enum PersonType { ADULT, CHILD, SENIOR };
- void setPersonType (PersonType person_type);
- PersonType getPersonType ();
- private:
- PersonType _person_type;
- };
那麼在定義getPersonType函數的時候我們得這麼寫:
- Person::PersonType Person::getPersonType ()
- {
- return _person_type;
- }
因爲函數所在的類Person是聲明在函數返回值之後的,所以在寫返回值的時候編譯器並不知道這個函數是在哪個類裏面。由於PersonTYpe是Person類的內部聲明的枚舉,所以在看到PersonType的時候,編譯器是找不到這個類型的。所以你就得在PersonTYpe前面加上Person::,告訴編譯器這個類型是屬於Person的。這看起來有點麻煩是吧。當你使用新的返回值語法的時候呢就可以這麼寫:
- auto Person::getPersonType () -> PersonType
- {
- return _person_type;
- }
因爲這次編譯器看到返回值類型PersonType的時候已經知道這個函數屬於類Person。所以它會到Person類中去找到這個枚舉類型。
當然上述應用只能說是一個奇技淫巧而已。並沒有幫我們多大的忙(代碼甚至都沒有變短)。所以還得引入C++11的另一個功能。
類型獲取(Decltype)
- int x = 3;
- decltype(x) y = x; // same thing as auto y = x;
上述代碼就使用了類型獲取功能。和函數返回值後置語法結合起來,可以有如下應用:
- template <typename Builder>
- auto
- makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )
- {
- auto val = builder.makeObject();
- // do stuff with val
- return val;
- }
前面的例子中這個函數的返回值是void,所以不需要爲返回值引入泛型。如果返回值是makeObject的返回值的話,那麼這個函數就得引入兩個泛型。現在又了類型獲取功能,我們就能在返回值中自動推斷makeObject的類型了。所以decltype確實爲我們提供了很大的便利。