重学C++ (十二) 模板特化和偏特化
2016-03-03 22:54
483 查看
一、模板的定义
1.类模板
[code]template <class T> class compare { public: bool IsEqual(T t1, T t2) { return t1 == t2; } }; int main() { char str1[] = "Hello"; char str2[] = "Hello"; compare<int> c1; compare<char *> c2; cout << c1.IsEqual(1, 1) << endl; //比较两个int类型的参数 cout << c2.IsEqual(str1, str2) << endl; //比较两个char *类型的参数 return 0; }
2.函数模板
[code]bool IsEqual(T t1, T t2) { return t1 == t2; } int main() { char str1[] = "Hello"; char str2[] = "Hello"; cout << IsEqual(1, 1) << endl; cout << IsEqual(str1, str2) << endl; return 0; }
二、模板特化
上述代码中,比较字符串是否相等,由于传入的参数是char *类型的,IsEqual函数模板只是简单的比较传入参数的值,即两个指针是否相等,因此结果为false。显然,这与我们的初衷不符。因此,上述模板需要对char *类型进行特别处理,即特化。1.类模板特化
[code]template <> //告诉编译器这是一个特化的模板 class compare<char *> //特化(char*) { public: bool IsEqual(char* t1, char* t2) { return strcmp(t1, t2) == 0; //使用strcmp比较字符串 } };
注意,如果是在类特化外部定义成员时,成员之前不能加template<>标记。
另外,我们可以只特化成员而不特化类,比如vector中,我们可以只特化push_back操作:
[code]template<> void vector<const char *>::push_back(const char *const &val) { //... }
类类型vector
2.函数模板特化
[code]template <> bool IsEqual(char* t1, char* t2) //函数模板特化 { return strcmp(t1, t2) == 0; }
三、模板偏特化
1.类模板的偏特化
当有多个模板形参时,我们可以只特化一部分形参而不是全部。c++标准库中的类vector的定义就是一个例子:
[code]template <class T, class Allocator> class vector { // … // }; template <class Allocator> class vector<bool, Allocator> { //…//};
上述例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。
2.函数模板的“偏特化”
严格来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。[code]template <class T> void f(T); (a)
根据重载规则,对(a)进行重载
[code]template < class T> void f(T*); (b)
如果将(a)称为基模板,那么(b)称为对基模板(a)的重载,而非对(a)的偏特化。
四、模板特化时的匹配
1.类模板的匹配
最优化的优于次特化的,即模板参数最精确匹配的具有最高的优先权例子:
[code]template <class T> class vector{//…//}; // (a) 普通型 template <class T> class vector<T*>{//…//}; // (b) 对指针类型特化 template <> class vector <void*>{//…//}; // (c) 对void*进行特化
每个类型都可以用作普通型(a)的参数,但只有指针类型才能用作(b)的参数,而只有void*才能作为(c)的参数
2.函数模板的匹配
非模板函数具有最高的优先权。如果不存在匹配的非模板函数的话,那么最匹配的和最特化的函数具有高优先权例子:
[code]template <class T> void f(T); // (d) template <class T> void f(int, T, double); // (e) template <class T> void f(T*); // (f) template <> void f<int> (int) ; // (g) void f(double); // (h) bool b; int i; double d; f(b); // 以 T = bool 调用 (d) f(i,42,d) // 以 T = int 调用(e) f(&i) ; // 以 T = int* 调用(f) f(d); // 调用(g)
相关文章推荐
- C++中虚函数功能的实现机制
- 面向对象程序设计-复习C++
- 利用C语言结构体模拟一个简单的JavaBean
- C语言结构体赋值2
- C语言结构体的引入
- 1096. Consecutive Factors (20)
- Problem G: C语言习题 n个数逆序
- c++中的字节对齐分析
- DSP 2812: 使用C++封装SCI
- Problem E: C语言习题 矩形法求定积分
- 同样简单的选择排序算法
- C++学习笔记53——纯虚函数与继承中的容器
- C++程序员如何向一个java工程师解释何为reference引用?
- Problem D、F: C语言习题 矩阵元素变换
- C++程序员如何向一个java工程师解释何为reference引用?
- c++ 函数的隐藏和覆盖
- Problem C: C语言习题 整数排序
- C++类的声明与实现中容易忽视的重定义默认参数的错误
- c++ 基类已经存在virtual修饰的同名成员函数,派生类加不加无所谓,都是virtual的
- 【C/C++学院】0907-象棋五子棋代码分析/寻找算法以及排序算法