// MaxTemplate.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- template <typename T>
- inline T const& max(T const& a, T const& b)
- {
- return a > b ? a : b;
- }
- //test
- int main()
- {
- int a = 0;
- int b = 0;
-
- //給a b 賦值為隨機數
- a = ::rand();
- b = ::rand();
- cout << "max(" << a << ", " << b << ") = " << ::max(a, b) << endl;
- double du1 = 0.0;
- double du2 = 0.0;
- du1 = (double)rand() / 10000;
- du2 = (double)rand() / 10000;
- cout << "max(" << du1 << ", " << du2 << ") = " << ::max(du1, du2) << endl;
- string str1 = "hello";
- string str2 = "test";
- cout << "max(" << str1 << ", " << str2 << ") = " << ::max(str1, str2) << endl;
- return 0;
- }
程式調用了 max()三次。第一次所給自變數是兩個 int,第二次所給自變數是兩個 double,最後一 次給的是兩個 std::string。每一次 max()均比較兩值取其大者。程式運行結果為:max(7,i): 42max(f1,f2): 3.4max(s1,s2): mathematics注意程式對max()的三次調用都加了首碼字 "::",以便確保被調用的是我們在全域命名空間(global namespace)中定義的 max()。標準庫內也有一個 std::max() template,可能會在某些情況下被調用,或在調用時引發模稜兩可(ambiguity,歧義性)。一般而言,templates 不會被編譯為「能夠處理任意類型」的單一實體(entity),而是被編譯為多個個別實體,每一個處理某一特定類型。因此,針對三個類型,max()被編譯成三個實體。 例如第一次調用 max():int i = 42; max(7,i) 使用的是「以int 為 template parameter T」的 function template,語意上等同於調用以下函數:inline int const& max (int const& a, int const& b){// 如果 a<b 就傳回 b,否則傳回 areturn a < b ? b : a;}以具體類型替換 template parameters 的過程稱為「執行個體化」(instantiation,或稱「實體化」)。過程中會產生 template 的一份實體(instance)。不巧的是,instantiation(執行個體化、執行個體化產品)和instance(實體)這兩個術語在OO(物件導向)編程領域中有其它含義,通常用來表示一個 class的具體對象(concrete object)。本書專門討論 templates,因此當我們運用這個術語時,除非另有明確指示,表達的是 templates 方面的含義。注意,只要 function template 被使用,就會自動引發執行個體化過程。程式員沒有必要個別申請執行個體化過程。類似情況,另兩次對 max()的調用被執行個體化為:const double& max (double const&, double const&);const std::string& max (std::string const&, std::string const&);如果試圖以某個類型來執行個體化 function template,而該類型並未支援 function template 中用到的操作,就會導致編譯錯誤。例如:std::complex<float> c1, c2; // 此類型並不提供 operator< max(c1,c2); // 編譯期出錯實際上,templates 會被編譯兩次:1. 不執行個體化,只是對 template 程式碼進行語法檢查以發現諸如「缺少分號」等等的語法錯誤。2. 執行個體化時,編譯器檢查 template 程式碼中的所有調用是否合法,諸如「未獲支援之函數調用」便會在這個階段被檢查出來。這會導致一個嚴重問題:當 function template 被運用而引發執行個體化過程時,某些時候編譯器需要用到template 的原始定義。一般情況下,對普通的(non-template)functions而言,編譯和連結兩步驟是各自獨立的,編譯器只檢查各個functions的聲明語句是否和調用語句相符,然而template 的編譯破壞了這個規則。解決辦法在第6章討論。眼下我們可以用最簡單的解法:把template 程式碼以 inline 形式寫在標頭檔(header)中。