一、類型推導
在前面反復分析過類型推導(包括前面提到的類模板參數推導CTAD),類型推導其實就是滿足C++語言這種強類型語言的要求即編譯期必須確定對象的數據類型。換一句話說,理論上如果編譯器中能夠自動推導所有的相關數據類型,也就是能夠滿足所有的情況,那么,C++編程就不會是現在這么難了。
在現在的C++標準中,包括最新的標準內,所有的類型推導其實都是有著嚴格的限制條件的。所以,這種自動推導就已經無法很簡單的應用。從早期的簡單的推導到中期的SFINAE技術再到最新的概念等控制等,其實都只是在進步,而未達到簡單方便的地步。
類型推導對強類型語言來說是一種非常重要的技術,特別是對于C++這種與反射天然不契合的語言來說,更是重要。如果有一天,C++語言可以輕松的原生支持反射后,這種類型推導,也就變得相對簡單多了。
二、C++11中的類型推導
在C++11標準中,做為第一個變化非常大的標準的演進,最主要的是auto和decltype兩種類型推導的方法。特別是auto,新的程序員可能還沒有什么問題,老的程序員可就要明白它與早期的auto的不同。最重的反而是decltype,這個關鍵字可以用來處理表達式的類型,當然也可以處理基礎的數據類型。
一般來說auto是根據初始化過程中的數據類型來推導相關數據類型而decltype則根據表達式的類型(一定要明白,表達式和數據類型變量的關系)。
同樣,C++11中提供了?std::declval這個模板函數,它提供了一個不需要構造即可獲取對象類型的方法,在某些場景下(如純虛類等)可以與decltype等共同進行更方便的類型推導。
三、C++14和17中的類型推導
C++14做為一個小版本的標準演進,進一步增強了auto的應用,特別是表達式也可以使用auto,比如Lambada表達也可以使用auto。同時,解決了前面提到過的拖尾類型,即decltype(auto)的使用。
在C++17中,引入了類模板參數的自動推導,也就是說,不必再顯示的指定模板參數,而是可以根據發現的構造函數來進行自動的推導并構造。另外,結構化綁定的引入做為一種新的初始化或者說解構的方式,更好的發展了auto的應用。同樣也進一步提高了Lambada表達式中對auto變量的捕獲能力。或者,往回看就會發現,auto的應用在不斷的提升,應用的場景也在不斷的普及,這才是標準發展的方向。
四、C++20中的類型推導
在C++20中,最讓人矚目的就是概念(Concepts)以及約束(Requires),而這兩種控制手段則極大的增強了對數據類型推導的控制。另外,做為C++標準演進過程最重要的一部分coroutines(協程),也極大的支持了對數據類型推導情況。不過,這種推導是內部實現控制的,而且協程的應用一直沒有被普及,所以目前大家暫時還可以不用給自己太多壓力。
最后,在C++20前模板的推導可能需要自定義推導規則,但在此之后,這種情況會越來越少,大多數編譯器可自動推導出來。
本文中提到的各自推導技術和方法(包括CTAD),都在前面有過具體的分析說明和舉例,此處只是為了整體貫連起來,就不再反復舉例了。當然,在C++標準文檔中對CTAD也有更詳細的說明,如果有興趣可以去查看。
五、總結
在前面反復分析過相關的類型推導技術,大家應該對其的復雜和難度有了一定的了解。不過,這種數據類型推導,對大多數的開發者來說并沒有什么感覺。因為普通的推導一般都是編譯器自行完成的,只有到模板和元編程技術中,才會主動的進行類型推導的控制或者說出現了自動推導的錯誤,這其實才是類型推導的真正的復雜之處。
大家可根據自己所處的實際情況,有針對性的進行數據類型推導的學習和實踐,而不需要一定掌握到某種深度的程度。