模板以及模板偏特化

很久没有写博客了,学习进入了迷茫期或者是困顿期,不知道下一步该怎么走了。一边想学习算法,扎实功底,一边又想学系统编程(网络编程和多线程编程)。

闲言少叙,书归正传。

最近看侯杰讲解STL,其中泛型我不是太明白,因此专门查了查资料,学习了一下。资料如下:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html

我自己学习的总结如下:

 

模板分为两种:函数模板和类模板。

 

函数模板的格式如下:

template<class name1,class name2***,class namen> returnType functionName(name1,name2****namen){}

调用模板函数时,需要直接传递进入实参,编译器会推算出所使用的类型。这就是传说中的实参推演。

 

类模板的声明格式如下:

template<class name1,class name2***,class namen> class classname{}

定义格式如下:

template<class name1,class name2***,class namen> returnType classname<name1,name2***,namen>::functionName(?????){}

类模板不存在实参推演的问题。因此每次使用需要指定类型。

 

模板形参分三种类型:类型形参,非类型形参,以及默认模板形参。

类型形参:就是我们最常使用的通过class或者typename定义的形参。例子如下:

 1 #pragma once
 2 #ifndef __TEMPLATE_DEMO__
 3 #define __TEMPLATE_DEMO__
 4 
 5 template <class T> class A
 6 {
 7 public:
 8     T g(T a, T b);
 9     A();
10 };
11 
12 template <class T> A<T>::A()
13 {}
14 
15 template <class T> T A<T>::g(T a, T b)
16 {
17     return a + b;
18 }
19 
20 template <class T1> void fun(T1 a, T1 b)
21 {
22     cout << a << endl;
23     cout << b << endl;
24 }
25 #endif // !__TEMPLATE_DEMO__
View Code

 

cpp调用代码如下:

 1 // ConsoleApplication37.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include "TemplateDemo.h"
 7 
 8 using namespace std;
 9 
10 
11 int main()
12 {
13     A<int> a;
14     int c = 1, d = 2;
15     cout << a.g(2,3.2) << endl;
16     fun(c,d);
17     system("pause");
18     return 0;
19 }
View Code

 

这里需要注意的是,所有的模板实现代码都需要在头文件中定义实现。

非类型形参:就是内置类型形参。

非类型形参在模板内部为常量,只能是整型,指针,引用中的一种,且在编译期间就必须是常量。例子如下:

 1 #pragma once
 2 #ifndef __TEMPLATE_DEMO__
 3 #define __TEMPLATE_DEMO__
 4 
 5 template<class T, int MAXSIZE> class Stack
 6 {
 7 
 8 private:
 9     T elements[MAXSIZE];
10     int count;
11 public:
12     Stack();
13     void push(T const&);
14     T pop();
15     T top() const;
16     bool empty() const
17     {
18         return count == 0;
19     }
20     bool full() const
21     {
22         return count == MAXSIZE;
23     }
24 };
25 
26 
27 template<class T, int MAXSIZE> Stack<T, MAXSIZE>::Stack() :count(0)
28 {
29 
30 }
31 
32 template<class T, int MAXSIZE> void Stack<T, MAXSIZE>::push(T const& elem)
33 {
34     if (count == MAXSIZE)
35     {
36         throw std::out_of_range("out of range stack is full");
37     }
38     elements[count] = elem;
39     ++count;
40 }
41 
42 template<class T, int MAXSIZE> T Stack<T, MAXSIZE>::pop()
43 {
44     if (count == 0)
45     {
46         throw std::out_of_range("out of range stack is empty");
47     }
48     T t = elements[count-1];
49     --count;
50     return t;
51 }
52 
53 template<class T, int MAXSIZE> T Stack<T, MAXSIZE>::top() const
54 {
55     if (count == 0)
56     {
57         throw std::out_of_range("out of range stack is empty");
58     }
59     return elements[count - 1];
60 }
61 
62 
63 
64 #endif // !__TEMPLATE_DEMO__
View Code

 

cpp调用代码如下:

 1 // ConsoleApplication38.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include "TemplateDemo.h"
 6 #include <string>
 7 #include <iostream>
 8 
 9 using namespace std;
10 
11 int main()
12 {
13     try
14     {
15         Stack<int, 20> int20stack;
16         Stack<int, 40> int40stack;
17         Stack<string, 40> stringstack;
18         int20stack.push(7);
19         cout << int20stack.pop() << endl;
20         system("pause");
21 
22         stringstack.push("hello");
23         cout << stringstack.top() << endl;
24         stringstack.pop();
25         stringstack.pop();
26         system("pause");
27         return 0;
28     }
29     catch (exception const& ex) {
30         cerr << "Exception: " << ex.what() << endl;
31         system("pause");
32         return EXIT_FAILURE;
33     }
34 }
View Code

 

 

默认模板形参:

可以为类模板的类型形参提供默认值,不能为函数模板的类型形参提供默认值,类和函数模板都可以为非类型形参提供默认值。

类模板如果有多个类型形参,且从某一个开始设置了默认值,则从这一个开始之后的形参,都需要设置默认值。

在定义类模板时,默认形参的值需要省略(vs2015验证不通过)。

实例如下:

 1 #pragma once
 2 #ifndef __TEMPLATE_DEMO__
 3 #define __TEMPLATE_DEMO__
 4 
 5 template<class T1=int, class T2> class Demo
 6 {
 7 public:
 8     int execute(T1 a, T2 b);
 9 };
10 
11 
12 template<class T1, class T2> int Demo<T1, T2>::execute(T1 a, T2 b)
13 {
14     return a + b;
15 }
16 
17 #endif // !__TEMPLATE_DEMO__
View Code

 

cpp调用代码如下:

 1 // ConsoleApplication41.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include "TemplateDemo.h"
 6 #include <iostream>
 7 
 8 using namespace std;
 9 
10 int main()
11 {
12     Demo<int,int> demo;
13     cout << demo.execute(1,3) << endl;
14     system("pause");
15     return 0;
16 }
View Code

 

编译后结果报错:缺少默认模板参数:参数2。

将头文件修改成如下形式:

 1 #pragma once
 2 #ifndef __TEMPLATE_DEMO__
 3 #define __TEMPLATE_DEMO__
 4 
 5 template<class T1=int, class T2=int> class Demo
 6 {
 7 public:
 8     int execute(T1 a, T2 b);
 9 };
10 
11 
12 template<class T1, class T2> int Demo<T1, T2>::execute(T1 a, T2 b)
13 {
14     return a + b;
15 }
16 
17 #endif // !__TEMPLATE_DEMO__
View Code

 

然后编译通过,运行结果为4.

 

 

模板偏特化:

就是说,我们通过模板编程来包含所有的类型,因此只需要一个模板方法就可以替代所有的类型了,但是,在一些特殊类型时,我们有更高效的实现方式,希望在使用这种类型时,我们使用这种更高效的实现,因此就有了模板偏特化的说法。

 1 #pragma once
 2 #ifndef __TEMPLATE_DEMO__
 3 #define __TEMPLATE_DEMO__
 4 #include <iostream>
 5 
 6 template<typename T1, typename T2> class Demo
 7 {
 8 public:
 9     int execute(T1,T2);
10 };
11 
12 template<> class Demo<double,double>
13 {
14 public:
15     int execute(double a, double b)
16     {
17         std::cout << "in double type:" << std::endl;
18         std::cout << "a;" << a << std::endl;
19         std::cout << "b;" << b << std::endl;
20         return a / b;
21     }
22 };
23 
24 template<typename T1> class Demo<T1, int>
25 {
26 public:
27     int execute(T1,int);
28 };
29 
30 
31 template<typename T1, typename T2> int Demo<T1, T2>::execute(T1 a, T2 b)
32 {
33     std::cout << "in generic:" << std::endl;
34     std::cout << "a;" << a << std::endl;
35     std::cout << "b;" << b << std::endl;
36     return a + b;
37 }
38 
39 template<typename T1> int Demo<T1, int>::execute(T1 a, int b)
40 {
41     std::cout << "in int type:" << std::endl;
42     std::cout << "a;" << a << std::endl;
43     std::cout << "b;" << b << std::endl;
44     return a * b;
45 }
46 
47 #endif // !__TEMPLATE_DEMO__
View Code

 

cpp代码如下:

 1 // ConsoleApplication42.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include "TemplateDemo.h"
 7 
 8 using namespace std;
 9 
10 int main()
11 {
12     Demo<short, short> demo1;
13     demo1.execute(1,2);
14 
15     Demo<int, int> demo2;
16     demo2.execute(1,2);
17 
18     Demo<double, double> demo3;
19     demo3.execute(1.2,1.2);
20 
21     system("pause");
22     return 0;
23 }
View Code

 

运行结果如下,不同的类型进入到不同的模板实例。

这里记录一个问题:在全特化中的实现中,如果单独定义,则会编译不通过。

 

转载于:https://www.cnblogs.com/lucy-lizhi/p/6807733.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值