1. 程式人生 > >C++ 11 模板函式的預設模板引數

C++ 11 模板函式的預設模板引數

關於預設的函式引數,有一條規則:

void defFunc(int i ,int j = 2,int k = 3) {
}

那就是預設實參必須在形參的右邊.

為什麼要這麼規定? 其實我們呼叫一下程式碼就可以發現,必須這樣:

defFunc(1); 預設等於 defFunc(1,2,3)
defFunc(1,8); 預設等於 defFunc(1,8,3)

如果不把預設實參放到形參的右邊,那麼我們的函式很可能就是:

defFunc("預設引數" ,2,3) 

很顯然我們就得引入一個標誌,告訴編譯器這裡是一個預設引數.

今天我們要重點講的是,函式模板和類模板預設模板引數型別的規則:

C++98開始支援引入函式模板和類模板,並且支援類模板的預設型別,但是C++98這個時候還不支援,函式模板預設型別. C++ 11引入了此規則.

template <typename T = int> void defFunc(T a) { //C++ 98不合法,C++ 11合法
}//可以這麼寫,但是沒有什麼意義,呵呵!自己想.

類模板預設引數型別和函式預設引數擁有一樣的規則:預設實參型別必須在形參的右邊.

template<class T, class T1 = int, class T2 = string> class myclass{ //合法

};

以下寫法是不合法的.

template<class T = int, class T1 , class T2 = string> class myclass2 { //不合法

};

原因其實和預設函式引數實參型別必須在形參右邊是一樣的。

類模板本身是一個大家族,模板類是一個具體的大家族中的成員,類似具體下面模板類的寫法:

myclass<int ,double ,string> m1; 

只是
myclass<T1,T2,T3>類模板中的一員而已.

和函式同樣的理由,如果不這麼做,那麼我們可以就必須引入一個標誌,告訴編譯器這是個預設型別,那麼就失去預設型別的意義了.

但是再想想,為什麼函式引數卻不需要遵守這個規則了呢??

肯定是由於某種原因,導致了此規則被破壞.

答案是:函式模板引數型別,編譯器支援預設型別的推導。

舉個例子:

template<typename T1, typename T2> void func(T1  t1, T2 t2) {
	cout << t1 << endl;
	cout << t2 << endl;
}

在這裡插入圖片描述

編譯器能夠根據函式的引數型別自動推匯出模板函式,但是模板類就不行,編譯器沒法自動幫模板類做引數型別的匹配。

下面的模板函式,預設引數型別就是

template<typename T1 = int, typename T2, typename T3> void func2(T2 t2,T3 t3,T1 t1 = 0) {
	cout << t1 << endl;
	cout << t2 << endl;
	cout << t2 << endl;
}

在函式中,可以看到預設的模板型別是不需要遵守必須在右邊的規定的.

在這裡插入圖片描述

因為編譯器也能夠很輕鬆的推匯出。