Just a little smile ^ ^

yoyo_zeng

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

3.1 函数模板

 1  
2
3 template <typename T>
4
5 inline int compare(const T &v1, const T &v2) //inline放在template之后
6
7 {
8
9 if (v1 < v2)
10
11 {
12
13 return -1;
14
15 }
16
17 if (v2 < v1)
18
19 {
20
21 return 1;
22
23 }
24
25 return 0;
26
27 }
28
29 string s1;
30
31 string s2;
32
33 compare(s1, s2) //用string 替代T创建compare.
34
35



T表示的实际类型由编译器所用的函数而确定.

使用函数模板时, 编译器会推断哪个模板实参绑定到模板形参,一旦编译器确定了实际的模板实参,就称它实例化了一个函数模板的实例, 实际上,编译器编写了一个函数实例.

 

3.2 模板类

 

关键字class or typename.

 1  
2
3 template <class Type> class tempclass
4
5 {
6
7 public:
8
9 tempclass();
10
11 Type func(void);
12
13 void func2(Type);
14
15 //...
16
17 private:
18
19 //...
20
21 };
22
23 tempclass<string> obj;
24
25 tempclass<vector<double>> obj;
26
27
28
29 typedef double T
30
31 template <typename T>
32
33 inline int compare(const T &v1, const T &v2){
34
35 T temp; /*将T定义为double的全局类型别名被T的类型形参所屏蔽,因此temp为绑定到模板形参的任意类型. */
36
37 //
38
39 }
40
41
42
43 template <typename T>
44
45 inline int compare(const T &v1, const T &v2){
46
47 typedef double T
48
49 T temp; //error, redeclares T
50
51 //
52
53 }
54
55



模板可以只声明不定义, 且同一模板的声明和定义中,模板形参的名字可以不同.

 1 template <typename parm, typename u >
2
3 parm fcn(parm *array, U value)
4
5 {
6
7 parm::size_type *p; /*编译器会无法辨识是size_type或是数据成员,默认是数据成员,则重定义.*/
8
9 typename parm::size_type * p; //typename告诉编译器姜size_type当做类型.
10
11 }



 

多个类型的实参必须完全匹配。

short i(9);

compare(i, 10); //error, ambiguous, compare(short, short), compare(int,int)

如果允许常规转换,则可以定义

 1 template <typename A, typename B>
2
3 inline int compare(const A &v1, const B &v2){
4
5
6
7 }
8
9 short i(9);
10
11 compare(i, 10); //ok
12
13
14
15 template <typename T>
16
17 inline int compare(const T &v1, const T &v2);
18
19 int a[10],b[20];
20
21 compare(a, b); /*error,当形参为引用时,数组不能转换为指针,a和b的类型不匹配.*/
22
23
24
25 template <typename T>
26
27 inline int compare(const T v1, const T v2);
28
29 int a[10],b[20];
30
31 compare(a, b); /*ok,非引用形参,对数组或函数类型的实参,都用常规指针转换,指向数组第一个元素和指向函数. */
32
33
34
35 int (*p)(const int&, const int&) = compare; //实例化compare(const int&, const int&);
36
37



在返回类型中使用形参。

1 template < typename C ,typename A, typename B>
2
3 inline C compare(const A &v1, const B &v2);
4
5 int i = 9;
6
7 short s = 10;
8
9 long l = compare<long>(i, s);



模板实参从左至右与与对应模板形参相匹配,只有最右边形参的显示模板实参可以忽略。

 

 1 //如果定义
2
3 template <typename A ,typename B, typename C>
4
5 inline C compare(const A &v1, const B &v2);
6
7 //必须像是指模板形参
8
9 long l =cmpare< int, short, long>(i, s);
10
11 long l = compare<long>(i, s); //error, long给了A
12
13
14
15 void func(int (*)(const int &, const int &));
16
17 void func(string (*)(const string &, const string &));
18
19 func(compare); //error, ambiguous
20
21 func(compare<int>); //ok,显示指定模板参数
22
23



普通函数只需要在源文件中声明,而定义类对象时,类定义必须可用,所以函数声明和类定义放在头文件中。

编译器实例化的时候,必须要能够访问函数模板定义和类模板定义,

包含编译模型

xxx.h

 1 #ifndef xxx
2
3 #define xxx
4
5 template <typename T>
6
7 inline int compare(const T v1, const T v2);
8
9 #include "xxx.cc"
10
11 #endif



 

xxx.cc

1 template <typename T>
2
3 inline int compare(const T v1, const T v2)
4
5 {
6
7 }



 

分别编译模型

xxx.cc

1 export template <typename T>
2
3 inline int compare(const T v1, const T v2);
4
5 #include "xxx.h"



 

xxx.h

1 template <typename T>
2
3 inline int compare(const T v1, const T v2)
4
5 {
6
7 }
8
9



类声明必须放在头文件中,头文件中的类定义体中不应该使用export关键字,如果在头文件中使用了export,则该头文件中只能被程序中的一个源文件使用。

xxx.h

 1 template <class Type> class tempclass
2
3 {
4
5 public:
6
7 tempclass();
8
9 Type func(void);
10
11 void func2(Type);
12
13 //...
14
15 private:
16
17 //...
18
19 };
20
21



xxx.cc

1 export template <class Type> class tempclass;
2
3 #include "xxx.h"



 

3.3 类模板成员函数

 

xxx.cc

1 template <class type> void tempclass<type>::func2(type)
2
3 {
4
5 }



 

3.4 类模板友元

 1 template <class Type> class tempclass
2
3 {
4
5 public:
6
7 tempclass();
8
9 Type func(void);
10
11 void func2(Type);
12
13 friend class friendclass;
14
15 friend void friendfunc(); /*普通友元,可以访问tempclass的任意实例的private和protected成员 */
16
17 template <class T> friend friendclass2;
18
19 template <class T> friend void friendfunc2(void);
20
21 /* 一般模板友元关系,模板类friendclass2和模板函数friendfunc2的任何实例都可以访问任何tempclass的任意实例的私有成员. */
22
23 //...
24
25 private:
26
27 //...
28
29 static std::size_t ctr;
30
31 };
32
33 template<class type> size_t tempclass<type>::ctr = 0;



 

类模板的模板友元函数定义有2种方式:
1.
将友元模板函数直接定义在类模板中。这种方式比较简单直接。

 1 template <typename T>class Number;
2
3 template <typename T> void print(const Number<T>& n);
4
5
6
7 template <typename T>
8
9 class Number {
10
11 public:
12
13 Number(T v){}
14
15 friend void print(const Number& n)
16
17 {
18
19 }
20
21 };
22
23 Number<int> n(1);
24
25 print(n);




2.
将友元模板函数声明在类模板中,定义在类模板之外。这种方式的写法,如果不小心,通常会出现编译没问题,链接时无法解析的错误。

 1 template <typename T>class Number;
2
3 template <typename T> void print(const Number<T>& n);
4
5
6
7 template <typename T>
8
9 class Number {
10
11 public:
12
13 Number(T v){}
14
15 friend void print<T>(const Number<T>& n);
16
17 };
18
19 template <typename T>void print<T> (const Number<T>& n) {}
20
21 Number<int> n(1);
22
23 print(n);



 

特定的模板友元关系

 1 template <class type> class foo; //必须先声明
2
3 template <class type> void func(const type&);
4
5 template <class Type> class tempclass
6
7 {
8
9 public:
10
11 friend class foo<char *>;
12
13 friend void func<char *>(char * const &);
14
15 friend class foo<type>;
16
17 friend void func<type>(const type &);
18
19 private:
20
21
22
23 };



 

3.5 函数模板特化

 

一个或多个模板形参的实际类型或实际值是指定的,特化的声明必须与模板相匹配.

使用模板特化的文件必须包含模板特化的声明.

 1 template <>
2
3 int compare<const char*>(const char * const &v1, const char * const &v2)
4
5 {
6
7 return strcmp(v1, v2);
8
9 }
10
11 int a = 2, b = 3;
12
13 const char *cp1 = "a", *cp2 = "b";
14
15 compare(a, b); //calls the generic version instantiated with int
16
17 compare(cp1, cp2); // calls the specialization
18
19
20
21 template <typename T> int compare(const T&v1, const T&v2)
22
23 {
24
25 if (v1 < v2) return -1;
26
27 if (v2 < v1) return 1;
28
29 return 0;
30
31 }
32
33 /* template <> int compare<const char*>(const char * const &v1, const char * const &v2); 声明放这则OK. */
34
35 int _tmain(int argc, _TCHAR* argv[])
36
37 {
38
39 const char *cp1 = "a", *cp2 = "b";
40
41 compare(cp1, cp2); /*无法编译, explicit specialization; 'int compare<const char*>(const T &,const T &)' has already been instantiated */
42
43 return 0;
44
45 }
46
47
48
49 template <> int compare<const char*>(const char * const &v1, const char * const &v2)
50
51 {
52
53 return strcmp(v1, v2);
54
55 }
56
57



3.6 类模板特化

 

 1 template <> class tempclass<const char*>
2
3 {
4
5 public :
6
7 void func2(const char *);
8
9 };
10
11 void tempclass<const char*>::func2(const char * v)
12
13 {
14
15 }



 

3.7 类成员特化

 

xxx.h

 1 template <class Type> class tempclass
2
3 {
4
5 public :
6
7 int compare(const Type&v1, const Type&v2);
8
9 };
10
11 int tempclass <const char *>::compare(const char * const &v1, const char * const &v2);



xxx.cc

 1 template <class Type>
2
3 int tempclass<Type>::compare(const Type &v1, const Type &v2)
4
5 {
6
7 if (v1 < v2) return -1;
8
9 if (v2 < v1) return 1;
10
11 return 0;
12
13 }
14
15
16
17 template <>
18
19 int tempclass <const char *>::compare(const char * const &v1, const char * const &v2)
20
21 {
22
23 return strcmp(v1, v2);
24
25 }
26
27



3.8 类模板的部分特化

 

 1 template <class T1, class T2> class some_tempclass
2
3 {
4
5 };
6
7 template <class T1> class some_tempclass<T1, int>
8
9 {
10
11 };
12
13 some_tempclass<int, string> obj; //use template <class T1, class T2> class some_tempclass
14
15 some_tempclass<string, int> obj2; //use template <class T1> class some_tempclass<T1, int>



 

3.9 重载和函数模板

 

 1 template <class T>
2
3 int compare(const T &v1, const T &v2);
4
5 template <class T1, class T2>
6
7 int compare(const &T1, const &T1, const &T2);
8
9 int compare(const char * const &v1, const char * const &v2);
10
11
12
13 const char *cp1 = "a", *cp2 = "b";
14
15 compare("a", "b"); /*call int compare(const char * const &v1, const char * const &v2); 普通函数优先级比函数模板更高. */
16
17 compare(1, 2); //call int compare(const T &v1, const T &v2);
18
19 compare(1, 1, 2); //call int compare(const &T1, const &T1, const &T2);
20
21 char *cp3 = "a", *cp3 = "b"; /*call int compare(const T &v1, const T &v2); 因为调用普通函数需要从char *转换为const char * */


posted on 2011-09-29 15:44  yoyo_zeng  阅读(253)  评论(0编辑  收藏  举报