一、概念

java 或 C# 中叫泛型:generic,但是C++中叫templates,templatea則完全不同,也不能説完全不同,但是牛逼的多,比泛型和那些託管語言牛逼的多。模板有點像宏,它可以讓你做很多事情,但是泛型卻非常受制於類型系統,以及其他很多因素,模板templates要強大的多。模板是一個巨大、複雜的話題。

二、什麼是模板?

模板允許你定義一個可以根據你的用途進行編譯的模板,如果是有意義的話。你可以讓編譯器基於一套規則為你寫代碼。所謂模板,就是讓編譯器基於你給編譯器的規則為你寫代碼。
例如:當我用模板寫函數時,我實際上做的是,創建一個藍本。所以當我調用這個參數時,我可以指定特定的參數,這個參數決定了放入到模板中的實際代碼。這就決定了我如何使用這個函數。

  1. 未用模板示例:同樣的代碼重載多次
#include<iostream>
#include<string>

void Print(int a) {
	std::cout << a << std::endl;
}

void Print(float a) {
	std::cout << a << std::endl;
}

void Print(std::string a) {
	std::cout << a << std::endl;
}

int main() {
	Print(1);
	Print(2.0f);
	Print("Hello World");

	std::cin.get();
}
  1. 使用C++ 模板
#include<iostream>

template<typename T>
void Print(T a) {
	std::cout << a << std::endl;
}

int main() {
	Print(1);
	Print(2.0f);
	Print("Hello World");

	std::cin.get();
}

三、原理

如果你完全沒有使用、調用模板函數,那麼這個函數就不是真的存在,這個函數只是一個模板,只有當我們調用的時候,這個函數才被真正的創建,

eg:模板函數參數命名錯誤,Visual Studio編輯器並不會提示錯誤❌️,早期版本的Visual Studio 可build通過,新版本已不可通過

#include<iostream>

template<typename T>
void Print(T value) {
	std::cout << valu << std::endl;
}

模板只有在它被調用時,才會被創建,因為它只是一個模板,不是實際的代碼。只有基於模板的使用情況,發送到編譯器,進行編譯後,才會具體化為真正的代碼。

四、模板的更多用處

模板絕不僅僅侷限於類型,也不侷限於函數。你可以創建一個整個的類基於模。實際上,大量的C++標準模板庫同樣完全使用了模板,

不用類型做模板參數:

#include<iostream>

template<int N>
class Array {
private:
	int arr[N];

public:
	int GetSize() const {
		return N;
	}
};

int main() {
	Array<5> arr;
	arr.GetSize();
	std::cout << arr.GetSize() << std::endl;

	std::cin.get();
}

改進類型版,更進一步模板化

#include<iostream>

template<typename T, int N>
class Array {
private:
	T arr[N];

public:
	int GetSize() const {
		return N;
	}
};

int main() {
	Array<int, 5> arr;
	arr.GetSize();
	std::cout << arr.GetSize() << std::endl;

	std::cin.get();
}

這種方式和C++的元編程(meta programming)很像,因為你可以看到,相比於實際編程,編譯器在編譯時,實際在編程。

很多遊戲工作室或軟件公司 實際上禁止使用模板,從來不用模板,我覺得這可能反應過度了,因為我任務模板非常有用,在日誌系統或其他的使用場景下,