Function Templates Template Argument Deduction Explict Template Arguments

  • Slides: 32
Download presentation
Function Templates • • 前言 定義函式樣板的實例化 Template Argument Deduction Explict Template Arguments Template Compilation

Function Templates • • 前言 定義函式樣板的實例化 Template Argument Deduction Explict Template Arguments Template Compilation Models Template Explicit Specialization Overloading Function Templates

定義函式樣板的定義格式如下: template <type parameter list> function definition 其中 type parameter list 的項目可以是: • type

定義函式樣板的定義格式如下: template <type parameter list> function definition 其中 type parameter list 的項目可以是: • type parameter: • typename type_parameter_name (ANSI C++) • class type_parameter_name (舊式的 C++) • nontype parameter: type constant_name 項目之間必須用逗號區隔開來。

範例: 函式樣板的非資料型態參數是用來指定出現在函式樣板定義 中的常數值。 template <typename T, int size> T min (const T (&a)[size]) {

範例: 函式樣板的非資料型態參數是用來指定出現在函式樣板定義 中的常數值。 template <typename T, int size> T min (const T (&a)[size]) { T min_val = a[0]; for (int i = 1; i < size; i++) if (a[i] < min_val) min_val = a[i]; return min_val; }

In many ways, templates work like preprocessor macros, replacing the templated variable with the

In many ways, templates work like preprocessor macros, replacing the templated variable with the given type. However, there are many differences between a macro like this: #define min(i, j) (((i) < (j)) ? (i) : (j)) and a template: template<typename T> T min (T i, T j) { return ((i < j) ? i : j) } Here are some problems with the macro: There is no way for the compiler to verify that the macro parameters are of compatible types. The macro is expanded without any special type checking.

The i and j parameters are evaluated twice. For example, if either parameter has

The i and j parameters are evaluated twice. For example, if either parameter has a post-incremented variable, the increment is performed two times. For example, after the evaluations: x = 5; y = 6; z = min(x++, y); variable x becomes 7, not 6. Because macros are expanded by the preprocessor, compiler error messages will refer to the expanded macro, rather than the macro definition itself. Also, the macro will show up in expanded form during debugging.

int ia[] = { 5, 2, 8, 3, 9}; 範例: int m = min(ia);

int ia[] = { 5, 2, 8, 3, 9}; 範例: int m = min(ia); T int, size 5 template <typename T, int size> T min (const T (&a)[size]) { T min_val = a[0]; int min (const int (&a)[5]) { … } for (int i = 0; i < size; i++) if (a[i] < min_val) min_val = a[i]; return min_val; } double da[] = { 5. 0, 2. 0, 8. 3}; double m = min(da); T double, size 3 double min (const double (&a)[3]) { … }

template <typename T> T min (T x, T y) { return (x < y)?

template <typename T> T min (T x, T y) { return (x < y)? x : y } unsigned int ui; // error: cannot instantiate min(unsigned int, int) // must be: min(int, int) or // min(unsigned int, unsigned int) int m = min(ui, 1024);

演繹時不考慮函式樣板資料型態參數中的 const 和 volatile 宣 告。 template <typename T> T min (const T *a,

演繹時不考慮函式樣板資料型態參數中的 const 和 volatile 宣 告。 template <typename T> T min (const T *a, int size) { … } int *ia = new int[10]; int m = min(ia, 10); // 產生 int min(const int *, int) double *da = new double[10]; // 產生 double min(const double *, int) double d = min(da, 10);

Explicit Template Arguments 當無法決定如何從函式樣板產生具體函式時、或需要自定產生 某種資料型態的具體函式時,我們可以在呼叫函式樣板時,明 白地指定出資料型態參數的種類。指定的格式如下: template_func<explicit type list>(argument list); 譬如: template <typename T>

Explicit Template Arguments 當無法決定如何從函式樣板產生具體函式時、或需要自定產生 某種資料型態的具體函式時,我們可以在呼叫函式樣板時,明 白地指定出資料型態參數的種類。指定的格式如下: template_func<explicit type list>(argument list); 譬如: template <typename T> T min (T x, T y) { return (x < y)? x : y } unsigned int ui; // min(unsigned int, unsigned int) unsigned int m = min<unsigned int>(ui, 1024);

範例: template < typename RT, typename T 1, typename T 2> RT sum (T

範例: template < typename RT, typename T 1, typename T 2> RT sum (T 1 x, T 2 y) { … } typedef unsigned int ui_type; char ch; ui_type ui; // error: RT can’t be deduced. ui_type loc 1 = sum(ch, ui); // ok: ui_type sum(char, ui_type) ui_type loc 1 = sum<ui_type, char, ui_type>(ch, ui);

範例: template < typename RT, typename T 1, typename T 2> RT sum (T

範例: template < typename RT, typename T 1, typename T 2> RT sum (T 1 x, T 2 y) { … } void manipulate(int (*pf)(int, char)); void manipulate(double (*pf)(float, float)); // error: which instantiation of sum? manipulate(sum); // ok manipulate(sum<double, float>);

若不會造成混淆的話,< 和 > 之間的資料類型有些可以省略。 template < typename RT, typename T 1, typename T 2>

若不會造成混淆的話,< 和 > 之間的資料類型有些可以省略。 template < typename RT, typename T 1, typename T 2> RT sum (T 1 x, T 2 y) { … } typedef unsigned int ui_type; char ch; ui_type ui; // ok: ui_type sum(char, ui_type) // T 1 和 T 2 可由引數的資料型態推演得到 ui_type loc 1 = sum<ui_type>(ch, ui); // ok: ui_type sum(char, ui_type) // T 1 和 T 2 可由 pf 的引數資料型態推演得到 ui_type (*pf)(char, ui_type) = sum<ui_type>;

Separation Compilation Model 把函式樣板的定義寫在一個. cpp 程式檔之中,然後在呼叫函 式樣板的程式檔中宣告此函式樣板。 // file: min. h // prog. cpp

Separation Compilation Model 把函式樣板的定義寫在一個. cpp 程式檔之中,然後在呼叫函 式樣板的程式檔中宣告此函式樣板。 // file: min. h // prog. cpp template <typename T> #include “min. h” T min (T x, T y) ; // declaration … // file: min. cpp export template <typename T> T min (T x, T y) { return (x < y)? x : y } int m = min(3, 4); 注意行首的 關鍵字 export

template <typename T> T min (T x, T y) { return (x < y)?

template <typename T> T min (T x, T y) { return (x < y)? x : y } template<> const char * min (const char *x, const char * y) { return strcmp(x, y) < 0? x : y; } int d = min(2. 0, 3. 0); // 產生 double min(double, double) int m = min(2, 3); // 產生 int min(int , int ) // 產生 const char * min(const char *, const char *) const char *cp = min(“book”, “apple”);

Overloading Function Templates 如一般函式,我們也可以定義超載函式樣板。譬如: template <typename T> T min(const vector<T>&); // #1 template <typename

Overloading Function Templates 如一般函式,我們也可以定義超載函式樣板。譬如: template <typename T> T min(const vector<T>&); // #1 template <typename T> T min(const T*, int); // #2 template <typename T> T min(T, T); // #3 // ordinary function const char *min(const char *, const char *); // #4

vector<int> iv(1024); int m 1 = min(iv); // #1 instantiation int ia[1024]; int m

vector<int> iv(1024); int m 1 = min(iv); // #1 instantiation int ia[1024]; int m 2 = min(ia, 1024); // #2 instantiation double d = min(3. 0, 4. 0); // #3 instantiation float f = min(3. 0, 4. 0); // #3 instantiation int m 3 = min(3, 4); // #3 instantiation const char *cp = min(“Y”, “N”); // #4 instantiation unsigned ui; int m 4 = min(3, ui); // error

範例: template <typename T> T min(T, T); template <typename T, typename U> T min(T,

範例: template <typename T> T min(T, T); template <typename T, typename U> T min(T, U); unsigned ui; int m 4 = min(3, ui); // ok int m 3 = min(3, 4); // error: ambiguous

範例: template <typename T> T sum(T, int); // #1, more general template <typename T>

範例: template <typename T> T sum(T, int); // #1, more general template <typename T> T sum(T*, int); // #2, more special int ia[1024]; int m 2 = sum(ia, 1024); // #2 instantiation