owned this note
owned this note
Published
Linked with GitHub
---
slideOptions:
transition: slide
---
<!-- .slide: data-transition="fade-in convex-out" -->
# c++ template
南天門日月卦長
---
## 回想之前教過的sort
如果現在有這些陣列需要排序:
1. int陣列
2. char陣列
3. double陣列
4. float陣列
5. long long陣列
6. ...
----
## 要寫好幾種sort!!
難道有幾個資料型別就要寫幾個sort嗎?
```cpp=
void int_sort(int s[],int n);
void char_sort(char s[],int n);
void double_sort(double s[],int n);
void float_sort(float s[],int n);
void long_long_sort(long long s[],int n);
//...
```
----
## 大同小異
這些sort雖然資料型態不一樣
但是程式碼的結構卻是一模一樣的
---
<!-- .slide: data-transition="fade-in convex-out" -->
## 洪荒時代( < 1990 C.E. )的做法
在本小節中
各位將看到古人們怎麼解決以上的問題
因為有些難度
想跳過的人可以直接去看[下一章節](#/6)的內容
---
## ```#define```
C/C++中```#define```是很有趣的東西
它可以讓你自訂一些字串來取代原本的字串
詳細請參考教學[C++ 巨集](http://en.cppreference.com/w/cpp/preprocessor/replace)
----
## #define範例
如果你寫的程式長這樣:
``` cpp=
#define mul(x,y) (x*y)
int main(){
cout << mul(3561,2) << '\n';
}
```
電腦(編譯器)看到的其實是這樣
``` cpp=
int main(){
cout << (3561*2) << '\n';
}
```
----
## 好幾行怎麼辦
如果有好幾行要define的話
可以利用**反斜線**```'\'```來進行換行
```cpp=
#define swap(a,b){\
auto tmp = a;\
a = b;\
b = tmp;\
}
int main(){
int x = 1, y = 2;
swap(x, y);
cout << x << ' ' << y << endl;
}
```
----
## 編譯器視角(調整過)
```cpp=
int main(){
int x = 1, y = 2;
{
auto tmp = x;
x = y;
y = tmp;
}
cout << x << ' ' << y << endl;
}
```
----
## 小心使用
各位覺得如果我這樣寫會發生什麼事呢?
```cpp=
#define mul(x,y) (x*y)
int main(){
cout << mul(3562-1,1+1) << '\n';
}
```
----
## 編譯器視角
要注意```#define```只是做字串取代而已
```cpp=
int main(){
cout << (3562-1*1+1) << '\n';
//3562-1*1+1 = 3562!!
}
```
---
## 利用 define 製造函數!
```cpp=
#include<iostream>
using namespace std;
#define max_func(func_name)\
int func_name(int a, int b){\
return a < b ? b : a;\
}
max_func(myMax)
int main(){
cout << myMax(7122, 2217);
}
```
----
## 編譯器視角
```cpp=
#include<iostream>
using namespace std;
int myMax(int a, int b){
return a < b ? b : a;
}
int main(){
cout << myMax(7122, 2217);
}
```
----
## 產生不同型態的sort
利用define的性質
我們可以稍微簡化產生不同型態sort的方法
```cpp=
#define make_sort(Type, func_name)\
void func_name(Type s[], int n){\
for(int i=1; i<n; ++i)\
for(int j=i; j && s[j]<s[j-1]; --j)\
swap(s[j],s[j-1]);\
}
make_sort(int, int_sort)
make_sort(double, double_sort)
```
----
## 編譯器視角
```cpp=
void int_sort(int s[], int n){
for(int i=1; i<n; ++i)
for(int j=i; j && s[j]<s[j-1]; --j)
swap(s[j],s[j-1]);
}
void double_sort(double s[], int n){
for(int i=1; i<n; ++i)
for(int j=i; j && s[j]<s[j-1]; --j)
swap(s[j],s[j-1]);
}
```
---
## 好難
剛剛教的define還是太麻煩了
而且好難
----
## 進入正題
template
---
<!-- .slide: data-transition="convex-in convex-out" -->
## template(樣板,模板)
分成
* [Function template](#/7)
* [Class template](#/8)
---
## Function template
又稱「通用函式」(Generic Function)
想像 Type 可以是int, double, char ...
這樣只要寫一個函式就好了!
```cpp=
template<typename Type>
void mySort(Type s[], int n){
for(int i=1; i<n; ++i)
for(int j=i; j && s[j]<s[j-1]; --j)
swap(s[j],s[j-1]);
}
int main(){
int s[] = {7, 1, 2, 2};
mySort(s, 4);
}
```
----
## 使用方法
在你想做成模板的函數前面加上template<>就行了
T會根據呼叫函數時傳入的input變成不同的形態
```cpp=
template<typename T>
T func_name(T input){
//do something
}
```
----
## 範例
```cpp=
template<typename T>
T add(T a, T b){
return a+b;
}
int main(){
int int_a = 7022,int_b = 100;
double d_a = 0.1, d_b = 7.022;
cout << add(int_a, int_b) << '\n';// 7122
cout << add(d_a, d_b) << '\n';// 7.122
}
```
----
## 同時有好幾個型態
同時有好幾個型態時可以用**逗號**```','```隔開
```cpp=
template<typename T, typename G>
int func_name(T a, G b){
//do something
}
```
----
## 範例
```cpp=
template<typename T, typename G>
int add(T a, G b,double c){
return a+b+c;
}
int main(){
int int_a = 7022;
double d_b = 99.7122;
cout << add(int_a, d_b, 0.5) << '\n';// 7122
}
```
----
## 不要讓編譯器有多餘的想像
以下的code會編譯失敗
因為編譯器不知道G到底是甚麼型態
```cpp=
template<typename T, typename G>
G add(T a, T b){
G res = a+b;// G到底是甚麼型態?
return res;
}
int main(){
double d_a = 0.1, d_b = 7.022;
cout << add(d_a, d_b) << '\n';
}
```
----
## 正確用法
這種情況使用函數時要用**角括號```<>```**
告訴編譯器你想用的型態
```cpp=
template<typename T, typename G>
G add(T a, T b){
G res = a+b;// G到底是甚麼型態?
return res;
}
int main(){
double d_a = 0.1, d_b = 7.022;
cout << add<double, double>(d_a, d_b) << '\n';
cout << add<double, int>(d_a, d_b) << '\n';
cout << add<int, double>(d_a, d_b) << '\n';
}
```
---
## Class template
又稱「通用類別」(Generic class)
想像 Type 可以是int, double, char ...
這樣只要寫一個struct/class就好了!
```cpp=
template<typename Type>
struct testType{
Type t;
int id;
};
int main(){
testType<double> data;
data.t = 0.7122;
data.id = 7122;
}
```
----
## 使用方法
在想做成模板的struct/class前面加上template<>
使用時要用**角括號```<>```**告訴編譯器你T想用的型態
```cpp=
template<typename T>
struct testType{
T t;
int id;
};
```
----
## 範例
```cpp=
template<typename T>
struct testType{
T t;
int id;
testType(T t, int id):
t(t), id(id){}
};
int main(){
testType<double> data(0.7122, 7122);
cout << data.t << ' ' << data.id;
}
```
----
## 好幾個型態
當然和Function template一樣可以支援好幾個型態
```cpp=
template<typename T, typename G>
struct Jinkela{
T NPK;
G shengdiyage;
};
Jinkela<int, string> jinkela;
int main(){
jinkela.NPK = 30000;
jinkela.shengdiyage = "American.shengdiyage";
}
```
---
## 下一步,STL!
在下一章節中,我們會介紹強大的STL
標準模板庫(Standard Template Library)
會用到大量template的概念
一定要熟悉喔