C++11 模板元編程 - 鴨子類型


模板為C++提供了鴨子類型(Duck typing)的特性。所謂鴨子類型,指的是代碼關注的不是對象的類型本身,而是它被如何使用的。例如,在使用鴨子類型的語言中,我們編寫一個函數可以接受一個任意類型的對象,只要它有走、游泳和嘎嘎叫方法。至于客戶給它傳入的是一只真正的鴨子,或是也能走、游泳和嘎嘎叫的其它類型對象,都沒有關系。但是如果傳入的對象中沒有這些需要被調用的方法,就將引發(fā)一個錯誤。

" When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck. - James Whitcomb Riley, 1849-1916"

我們看下面這個例子:

template<typename T>
T max(const T& t1, const T& t2)
{
    return (t1 > t2)? t1 : t2;
}

max,只約束入參類型T支持>比較運算,而不關心它的具體類型。例如我們可以為max傳入intfloat或者是實現了了opertator >的任何對象。

直到現在,C++中模板對入參的約束都是通過對入參的使用方式來隱式體現的。而有的語言卻可以顯示約束。例如對于如下Haskell代碼:

max' :: (Ord a) => a -> a -> a
max' x y
    | x > y     = x
    | otherwise = y

如上max的定義前面通過函數聲明:max' :: (Ord a) => a -> a -> a約束了入參的類型a必須滿足Ord類型類的約束。類型類用于規(guī)范一組類型應該滿足的特征,例如Ord要求滿足它的類型必須能夠進行標準的比較操作,如<><=>=等。

C++17標準有可能會引入concept特性用來支持上述haskell中對類型特征進行顯示約束的能力。顯示化類型約束可以讓代碼更容易被理解,讓編譯器可以更準確的報告錯誤或者對代碼更好地做出優(yōu)化,同時也可以讓IDE對語言更好地支持。

鴨子類型為程序的書寫帶來了很多便利性,基本上動態(tài)語言(Python、Ruby)以及擁有類型推導的靜態(tài)語言(C++、Haskell、Scala)都有這個特性。區(qū)別在于動態(tài)語言一般是在運行期發(fā)現類型不滿足約束,而靜態(tài)語言通過強大的類型推導可以在編譯期就發(fā)現錯誤。

回到最后,我們思考下,如果把C++模板元編程當做一門獨立的語言,它自身是否支持鴨子類型呢?

答案很明確,雖然模板為“運行時C++”提供了鴨子類型的能力,但模板元編程自身卻不支持鴨子類型。

例如下面的元函數明確要求其入參的型別為類型,所以你可以這樣使用SizeOf<int>。但是一旦你傳入一個數值SizeOf<5>,它就會報錯。

template<typename T>
struct SizeOf
{
    using Result = __int(sizeof(T));
};

我們之前總結過,模板可以操作的計算對象大體可以分為數值和類型兩大類,一旦我們把模板當做編譯期函數來看,就會發(fā)現它是強類型的。一個模板聲明其入參是數值型,就不能接收類型作為入參,反之亦然!這就是為何我們?yōu)榱颂岣咴瘮档慕M合復用能力,將所有的數值也封裝成了類型。我們統一模板元編程的計算對象類型,就相當于把一切都變成了鴨子,間接地也得到了鴨子類型的好處。

最后,我們單獨看待模板元編程的時候,它相當是一門解釋型語言!C++編譯器直接面對模板元編程的源代碼進行編譯期計算,這時我們可以將C++編譯器看做是模板元編程的解釋器,它一邊解釋一邊執(zhí)行,解釋結束之時也是程序執(zhí)行完畢之時。有趣吧?在這個角度看模板元編程反而更像是一門腳本語言。


總結:兩階段的C++語言

返回 C++11模板元編程 - 目錄

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 134,915評論 18 139
  • 對于連續(xù)兩個右尖括號>, 那么它們之間需要一個空格來進行分隔,以避免發(fā)生編譯時的錯誤。 C++98編譯器會把>>優(yōu)...
    認真學計算機閱讀 1,235評論 0 7
  • 問題:什么是泛型編程?泛型編程的代表作品STL是一種高效、泛型、可交互操作的軟件組件。STL以迭代器 (Itera...
    認真學計算機閱讀 2,087評論 0 8
  • 吐槽是很耗精力的事情。比如《上線2》吐槽產品和美工,越寫越覺得犯惡心。跟負能量的人聊天也是這樣的,非常的壓抑。以前...
    xxwade閱讀 519評論 0 1
  • 游戲可以指導人生,因為“玩”往往是一種預演,能讓你未來越來越卓越。 《富爸爸窮爸爸》這本書給我?guī)砹撕芏鄦⒌希热?..
    EffyGuo閱讀 678評論 0 4