1. 程式人生 > >視頻筆記 CppCon 2015:Marshall Clow “Type Traits - what are they and why should I use them?"

視頻筆記 CppCon 2015:Marshall Clow “Type Traits - what are they and why should I use them?"

for -- per 是的 point 分類 ace ner null

Video: CppCon 2015:Marshall Clow “Type Traits - what are they and why should I use them?" https://www.youtube.com/watch?v=VvbTP_k_Df4 如果你需要寫關於不同類型的代碼,而不是具體的類型,你可能需要了解Type Traits 4:47 C++多少種類型?14 技術分享
  • void, nullptr: 只有一個成員在這個type裏面
  • struct 實際上和class 是一樣的,只是default access是public
  • array vs pointer: array有一片物理區域,pointer僅僅是個地址。pointer可以為空
8:00 類型分類 技術分享

08:21 type trait的定義 技術分享

就是一個結構,裏面包含模板的類型信息 例如,下面是個簡單用法,輸出true/false #include <iostream> #include <type_traits> std::cout << std::is_floating_point<float>::value << ‘\n‘; // true std::cout << std::is_floating_point<int>::value << ‘\n‘
; // false std::rank的用法,輸出int std::cout << std::rank<float>::value << ‘\n‘; // 0 std::cout << std::rank<int[1][1]>::value << ‘\n‘; // 2 std::cout << std::rank<int[2][3][4]>::value << ‘\n‘; // 3 有些可以輸出type std::remove_const<const
int>::type --> int std::remove_const<int>::type--> int BTW:
  1. std::is_permulation 比較兩個序列是否相同,順序可以不同
  2. std::enable_if & SAFINAE
enable_if 的主要作用就是當某個 condition 成立時,enable_if可以提供某種類型。enable_if在標準庫中通過結構體模板實現的 SFINAE 的的全稱是 Substitution Failure Is Not An Error SFINAE 是C++ 的一種語言屬性,具體內容就是”從一組重載函數中刪除模板實例化無效的函數” 19:20 這個視頻認為SFINAE是C++裏第二醜陋的縮略語。第一是RAII,因為根本就無法讀出來。 下面的例子不是來自本視頻 // long multiply(int i, int j) { return i * j; } template <class T> typename T::multiplication_result multiply(T t1, T t2) { return t1 * t2; } void test() { multiply(4, 5); // error } error C2893: Failed to specialize function template ‘T::multiplication_result multiply(T,T)‘ 如果把第一行的註釋去掉,這個error就會消失。這就是因為SFINAE原則,編譯器會嘗試所有的匹配,找到最合適的,其它不合適的有錯也忽略。 19:48 SFINAE Example int func(...) { return 0; } template <typename T> typename std::enable_if<std::is_integral<T>::value, int>::type func(T val) { return 1; } int func(float f) { return 2; } void test() { std::cout << func(nullptr) << " "; std::cout << func(2) << " "; std::cout << func(2.f) << " "; std::cout << func(2.0) << "\n"; } 輸出: 0 1 2 2 第1行是C語言的不定參數的函數,經典例子是printf,和C++11的variadic arguments 不同。這一行匹配的優先級最低。 第4行,如果T不是整數類型時,會產生編譯錯誤。根據SFINAE原則,使用其它的函數來匹配。 31:40 可以針對一些類型提供優化 32:00 優化的例子 技術分享

每個人都覺得自己實現的vector會比stl的好。但事實上,STL裏面的實現包含許多corner cases,非常復雜。 strong exception guarantee: 要麽完全成功,要麽出錯拋異常,並且需要完全恢復的操作前的狀態。例如,如果vector內存reserve不夠,需要申請新的內存,並且把已經有的對象拷貝進入新內存。如果拷貝到一半出錯,需要完全恢復這些操作,讓vector恢復到之前的狀態,並且拋出異常。 技術分享

拷貝的代價很高(需要創建,構造,析構舊對象)。如果T支持move,可以利用move提高效率。但是如果move構造函數會拋出異常,既無法繼續,又無法恢復!所以,必須要求no throw move-constructible! no throw意味著move永遠都能成功。並不是所有的T都能實現no throw的,需要特別留意。 技術分享

如果vector裏面是int,或者T是個結構只包含基本類型。只要申請新內存,拷貝內存(never throw),釋放舊內存,效率可言很高。有一種type trait叫做trivially copyable描述這種情況。

技術分享

這些都不是必要的,沒有這些也能正確實現。但是有了這些,可以優化得很好。

43:06 Questions
  • 44:00 可以生成自己的type trait嗎?可以。例如,std::is_floating_point,如果自己實現該怎麽實現。針對float, double, long double這幾種類型特化,返回true,默認返回false。有方法甚至可以實現這樣的type trait: 一個結構是否包含一個member function叫做foo,並且參數是什麽什麽,返回什麽。
  • 47:05 SFINAE 的例子,一般有兩種實現,一種是使用enable_if,另一種...enable_if 有什麽優勢?這種方法更簡單清晰,不容易出錯。具體見視頻。
  • 50:16 是的,將來 concept 的引入會很大程度的改變現在的實現

視頻筆記 CppCon 2015:Marshall Clow “Type Traits - what are they and why should I use them?"