C++模板的特化与偏特化
http://cppblog.com/SmartPtr/archive/2007/07/04/27496.html
(1) 类模板
定义一个栈的类模板,它可以用来容纳不同的数据类型
template <class T>
class stack {
private:
list* top;
public:
stack();
stack(const stack&);
~stack();
void push(T&);
T& pop();
//…
};
类模板的使用除了要在声明时指明模板参数外,其余均与普通的类相同,例如:
stack<int> int_stack;
stack<char> ch_stack;
stack<string> str_stack;
int_stack.push();
ch_stack.push(‘z’);
str_stack.push(“c++”);
(2) 函数模板
假设现在要定义一个max函数来返回同一类型(这种类型是允许比较的)两个值的最大者.
模板函数的使用与普通非模板函数使用相同,因为模板函数的参数类型可以从其传入参数中解析出来
template<class T>
T mymax(const T&t1, const T&t2)
{
return t1 < t2 ? t2 : t1;
} void main()
{
int t1 = , t2 = ;
cout << mymax(t1, t2);
}
3.模板的特化
(1) 类模板特化
有时为了需要,针对特定的类型,需要对模板进行特化,也就是特殊处理.例如,stack类模板针对bool类型,因为实际上bool类型只需要一个二进制位,就可以对其进行存储,使用一个字或者一个字节都是浪费存储空间的.
template <class T>
class stack {};
template < >
class stack<bool> { //…// };
上述定义中template < >告诉编译器这是一个特化的模板。
(2) 函数模板的特化
看下面的例子
main()
{
int highest = mymax(,);
char c = mymax(‘a’, ’z’);
const char* p1 = “hello”;
const char* p2 = “world”;
const char* p = mymax(p1,p2);
}
前面两个mymax都能返回正确的结果.而第三个却不能,因为,此时mymax直接比较两个指针p1 和 p2 而不是其指向的内容.
针对这种情况,当mymax函数的参数类型为const char* 时,需要特化。
template <class T>
T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
} template <>
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < ) ? t2 : t1;
}
现在mymax(p1,p2)能够返回正确的结果了。(这个例子在扯淡,vs2015运行没问题)
模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的。
模板分为类模板与函数模板,特化分为全特化与偏特化。全特化就是限定死模板实现的具体类型,偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。
4.模板的偏特化
模板的偏特化是指需要根据模板的某些但不是全部的参数进行特化,或者将T偏特化为T* 也是属于偏特化
(1) 类模板的偏特化
例如c++标准库中的类vector的定义
template <class T, class Allocator>
class vector { // … // };
template <class Allocator>
class vector<bool, Allocator> { //…//};
这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。
(2) 函数模板的偏特化
(模板函数不能偏特化,但是可以重载。)为什么不能偏特化?
严格的来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。
template <class T> void f(T); (a)
根据重载规则,对(a)进行重载
template < class T> void f(T*); (b)
5.模板特化时的匹配规则
(1) 类模板的匹配规则
最优化的优于次特化的,即模板参数最精确匹配的具有最高的优先权
例子:
template <class T> class vector{//…//}; // (a) 普通型
template <class T> class vector<T*>{//…//}; // (b) 对指针类型特化
template <> class vector <void*>{//…//}; // (c) 对void*进行特化
每个类型都可以用作普通型(a)的参数,但只有指针类型才能用作(b)的参数,而只有void*才能作为(c)的参数
(2) 函数模板的匹配规则
非模板函数具有最高的优先权。如果不存在匹配的非模板函数的话,那么最匹配的和最特化的函数具有高优先权
例子:
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,,d) // 以 T = int 调用(e)
f(&i) ; // 以 T = int* 调用(f)
f(d); // 调用(g)
参考effective c++条款25
class WidgetImpl
{
public:
WidgetImpl(){}
~WidgetImpl(){}
private:
std::vector<double>v;
}; class Widget
{
private:
WidgetImpl* pImpl;
public:
void swap(Widget& other)
{
using std::swap;
swap(pImpl, other.pImpl);
}
}; //将std::swap特化,与STL容器保持一致,所有STL容器也都提供public swap成员函数和std::swap特化版本(用以调用前者)
namespace std
{
template<>
void swap<Widget>(Widget& a, Widget& b)
{
a.swap(b);
}
}
//考虑类模板的情况
template<class T>
class WidgetImpl
{
public:
WidgetImpl(){}
~WidgetImpl(){}
private:
std::vector<double>v;
}; template<class T>
class Widget
{
private:
WidgetImpl<T>* pImpl;
public:
void swap(Widget<T>& other)
{
using std::swap;
swap(pImpl, other.pImpl);
}
}; //以下代码偏特化函数模板(std::swap),但c++只允许对类模板偏特化,函数模板不能偏特化
namespace std
{
template<class T>
void swap<Widget<T>>(Widget<T>& a, Widget<T>& b)
{
a.swap(b);
}
}
C++模板的特化与偏特化的更多相关文章
- C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)
1. 主版本模板类 首先我们来看一段初学者都能看懂,应用了模板的程序: 1 #include <iostream> 2 using namespace std; 3 4 template ...
- C++中模板的特化与偏特化
1.引言 C++中的模板分为类模板和函数模板,虽然它引进到C++标准中的时间不是很长,但是却得到了广泛的应用,这一点在STL中有着充分的体现.目前,STL在C++社区中得到了广泛的关注.应用和研究.理 ...
- [转]C++中模板的特化与偏特化
转载自:http://hi.baidu.com/klcdyx2008/blog/item/5adbf77b79f316f90bd1873c.html 1.引言C++中的模板分为类模板和函数模板,虽然它 ...
- 【校招面试 之 C/C++】第2题 函数模板、类模板、特化、偏特化
1.C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样 ...
- C++ 模板的全特化与偏特化
模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的. 模板分为类模板与函数模板,特化分为全特化与偏特化.全特化就是限定死模板实现的具体类型,偏特化就是如果这 ...
- oop &&GP 模板 ---> 特化和偏特化
OOP面向对象编程 GP泛型编程(generic programming) 两者的主要区别就是OOP将数据和对数据的操作放在一起, GP就是将数据和操作独立开来 GP: 数据就是container ...
- C++模板特化与偏特化
C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样显然 ...
- C++模板函数只能全特化不能偏特化
C++模板函数只能全特化不能偏特化
- C++模板显式实例化,隐式实例化,特化(具体化,偏特化)辨析
最近再次看C++ PRIMER PLUS的时候看到这个部分感觉讲得很烂,前后口径不一致,所以写个辨析让自己明白的同时也希望对此不太清楚的朋友能搞懂. 总结一下,C++只有模板显式实例化(explici ...
随机推荐
- 274 H-Index H指数
给定一位研究者的论文被引用次数的数组(被引用次数是非负整数).写一个方法计算出研究者的H指数.H-index定义: “一位科学家有指数 h 是指他(她)的 N 篇论文中至多有 h 篇论文,分别被引用了 ...
- FCC 基础JavaScript 练习6
1.对象和数组很相似,数组是通过索引来访问和修改数据,对象是通过属性来访问和修改数据的, 对象适合用来存储结构化数据,就和真实世界的对象一模一样,比如一只猫. 任务 创建一个叫做myDog的对象,它里 ...
- react Native环境 搭建
react Native的优点:跨平台 低投入高回报 性能高 支持动态更新.一才两用(ios和Android) 开发成本第 代码复用率高.windows环境搭建react Native开发环境1.安装 ...
- zencart,分类,所有,显示
改的文件:includes/classes/category_tree.php,最简单的修改 if (!isset($first_element)) { $first_element = ...
- MFC_2.4 组合框和图片控件
组合框和图片控件 1.拖控件 图片属性更改Type 为Bitmap 名字也要改,不能为IDC_STATIC 绑定变量控件,重命名. 2.初始化 // 设置一个定时器,用于更新图片 SetTimer(0 ...
- .net core Elasticsearch 查询更新
记录一下: 数据结构如下: public class ESUserTransaction { public long AccountId { get; set; } public string Var ...
- CAD创建组(网页版)
主要用到函数说明: _DMxDrawX::CreateGroup 创建组.如果组名已经存在,就把实体加入组中.详细说明如下: 参数 说明 BSTR pszName 组名.,如果为空,创建匿名组 IDi ...
- 反转链表_JAVA
package algorithms; /* * * * 输入一个链表,反转链表后,输出新链表的表头. * public class ListNode { int val; ListNode next ...
- blog笔录1
(1)虚拟主机 (2)部署 部署完成后刷新页面会看到笑脸,在Home分组下控制器Application/Home/Controller/IndexController.class.php下定义显示 ( ...
- svn更新报错Please execute the 'Cleanup' command.
更新svn报错 要Clearnup一下就可以再更新了 点击svn中 clear up ok之后恢复正常