儲存了一堆文件,消化一下。
Default template arguments for function templates 以下這個程式碼,在C++98是不可行,但是C++11可以的。
1 2 3 4 5 6 7 template <typename T = int> void Foo(T t = T()) { } Foo(12L); // Foo<long> Foo(10.1); // Foo<double> Foo('A'); // Foo<char> Foo(); // Foo<int>
根據Stackoverflow 的說法,可以寫類似這樣的Code>
1 2 3 template <typename Iterator, typename Comp = std::less<Iterator>> void sort(Iterator beg, Iterator end, Comp c = Comp()) { }
不過當Function Template在Argument deduction時,可能會有以下的問題。
1 2 3 4 5 6 template <typename B, typename T = int> void Bar(B b = B(), T t = T()) {} Bar(10); // Bar<int, int> Bar(10L); // Bar<long, int> Bar(10L, 20L); // Bar<long, long> Bar(); // Compile error, couldn't deduce template parameter ‘B’
同樣的在Function Template overload的時候,也是地雷區。
1 2 3 4 5 template <typename T = int> void Foo(T t = T()) {} template <typename B, typename T = int> void Foo(B b = B(), T t = T()) {} Foo(12L); // Compile error, ‘Foo(long int)’ is ambiguous // void Foo(T) [with T = long int] and void Foo(B, T) [with B = long int; T = int] Foo(); // Compile OK, choose the first function
C++真是細節有夠多的程式語言。
Explicit conversion operators 在C++98的時候,explicit
能做的就只有這樣。
1 2 3 4 5 6 class Test1 { public: explicit Test1(int) {} }; Test1 t1(10); Test1 t2 = 20; // compile error
而對這樣的處理無能為力。
1 2 3 4 5 6 7 8 9 10 11 12 class Test1 { public: explicit Test1(int) {} }; class Test2 { int x; public: Test2(int i) : x(i) {} operator Test1() { return Test1(x); } }; Test2 t1 = 10; Test1 t2 = t1;
t2被偷偷轉換成Test1類型而無法輕易發現,在C++11之後,增加了這樣的能力。
1 2 3 4 5 6 7 8 9 class Test2 { int x; public: Test2(int i) : x(i) {} explicit operator Test1() { return Test1(x); } }; Test2 t1 = 10; Test1 t2 = (Test1)t1; Test1 t3 = t1; // Compile error
不過bool算是例外。
1 2 3 4 5 6 7 8 9 10 11 12 class Test3 { public: explicit operator bool() { return true; } }; void Foo() { Test3 t3; if (t3) { // if constructor's bool conversion is treated as explicit. } bool b = t3; // Compile error }
在C語言可以這樣寫沒問題
不過在C++98,用std::vector
的時候,就只能寫成這樣。
1 2 3 4 std::vector<int> a; a.push_back(1); a.push_back(2); a.push_back(3);
支援Initializer lists
之後,終於可以寫出比較美觀的程式碼
1 std::vector<int> a = {1, 2, 3};
你也在自己的城市中使用Initializer lists,如下:
1 2 3 4 5 6 7 template <typename T> void print(const initializer_list<T>& nums) { for (auto num : nums) cout << num << endl; } print({1, 2, 3, 4});
既然有了Initializer lists之後,C++11更進一步將Initialization簡化,使用同樣的語法來做初始化。 Case 1:
1 2 3 4 5 6 7 struct C { int a; int b; C(int i, int j) {} }; C c {0,0}; //C++11 only. Equivalent to: C c(0,0);
Case 2
1 int* a = new int[3] { 1, 2, 0 }; //C++11 only
Case 3
1 2 3 4 struct X { int a[4]; X() : a{1,2,3,4} {} //C++11, member array initializer };
Case 4:
1 2 3 4 struct C { int a = 7; //C++11 only };
更進一步,將Initializer list和 Uniform initialization雙見合併。
1 2 map<string, string> singers ={ {"Lady Gaga", "+1 (212) 555-7890"}, {"Beyonce Knowles", "+1 (212) 555-0987"}};
這樣的程式碼易讀許多。