C++模板之特化与偏特化详解
2019独角兽企业重金招聘Python工程师标准>>>
C++函数模板与类模板实例解析_C 语言_脚本之家
http://www.jb51.net/article/53746.htm
C++关键字typename的深入理解_C 语言_脚本之家
http://www.jb51.net/article/37565.htm
深入分析:C++模板究竟会使代码膨胀吗_C 语言_脚本之家
http://www.jb51.net/article/36209.htm
这篇文章主要介绍了C++模板之特化与偏特化详解,本文讲解了什么是C++模板、模板特化、模板偏特化、特化与偏特化的调用顺序等内容,需要的朋友可以参考下
前言
说到C++模板,这个已经不是什么新东西了,自己在实际开发中也用过;对于C++模板特化和偏特化,对于别人来说,已经不是什么新东西了,但是对于我来说,的确是我的盲区,那天在群里讨论这个问题,自己对于这部分确实没有掌握,又联想到在《STL源码剖析》一书中,对于此也是有着介绍。所以,今天就对此进行详细的总结,以备后忘。
C++模板
说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板。我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样显然不利于程序的扩充和维护。C++模板就应运而生。C++的模板提供了对逻辑结构相同的数据对象通用行为的定义。这些模板运算对象的类型不是实际的数据类型,而是一种参数化的类型。C++中的模板分为类模板和函数模板。
类模板如下:
#include <iostream>
using namespace std;
template <class T>
class TClass
{
public:
// TClass的成员函数
private:
T DateMember;
};
函数模板如下:
template <class T>
T Max(const T a, const T b)
{
return a > b ? a : b;
}
模板特化
有时为了需要,针对特定的类型,需要对模板进行特化,也就是所谓的特殊处理。比如有以下的一段代码:
#include <iostream>
using namespace std;
template <class T>
class TClass
{
public:
bool Equal(const T& arg, const T& arg1);
};
template <class T>
bool TClass<T>::Equal(const T& arg, const T& arg1)
{
return (arg == arg1);
}
int main()
{
TClass<int> obj;
cout<<obj.Equal(2, 2)<<endl;
cout<<obj.Equal(2, 4)<<endl;
}
类里面就包括一个Equal方法,用来比较两个参数是否相等;上面的代码运行没有任何问题;但是,你有没有想过,在实际开发中是万万不能这样写的,对于float类型或者double的参数,绝对不能直接使用“==”符号进行判断。所以,对于float或者double类型,我们需要进行特殊处理,处理如下:
#include <iostream>
using namespace std;
template <class T>
class Compare
{
public:
bool IsEqual(const T& arg, const T& arg1); //在类的定义中,成员函数中即使使用了模板参数也不要在函数声明前放置模板说明。
};
// 已经不具有template的意思了,已经明确为float了
template <>
class Compare<float>
{
public:
bool IsEqual(const float& arg, const float& arg1);
};
// 已经不具有template的意思了,已经明确为double了
template <>
class Compare<double>
{
public:
bool IsEqual(const double& arg, const double& arg1);
};
template <class T>
bool Compare<T>::IsEqual(const T& arg, const T& arg1) //在除了模板类的定义以外,使用模板类时一般都要指定模板参数。这里也不例外。
{
cout<<"Call Compare<T>::IsEqual"<<endl;
return (arg == arg1);
}
//模板特化以后,实际上其本身已经不是templatized,所以这里在类外面定义函数时,已经不使用template模板说明了。
bool Compare<float>::IsEqual(const float& arg, const float& arg1)
{
cout<<"Call Compare<float>::IsEqual"<<endl;
return (abs(arg - arg1) < 10e-3);
}
bool Compare<double>::IsEqual(const double& arg, const double& arg1)
{
cout<<"Call Compare<double>::IsEqual"<<endl;
return (abs(arg - arg1) < 10e-6);
}
int main()
{
Compare<int> obj;
Compare<float> obj1;
Compare<double> obj2;
cout<<obj.IsEqual(2, 2)<<endl;
cout<<obj1.IsEqual(2.003, 2.002)<<endl;
cout<<obj2.IsEqual(3.000002, 3.0000021)<<endl;
}
模板偏特化
上面对模板的特化进行了总结。那模板的偏特化呢?所谓的偏特化是指提供另一份template定义式,而其本身仍为templatized;也就是说,针对template参数更进一步的条件限制所设计出来的一个特化版本。这种偏特化的应用在STL中是随处可见的。比如:
template <class _Iterator>
struct iterator_traits
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
// specialize for _Tp*
template <class _Tp>
struct iterator_traits<_Tp*>
{
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
// specialize for const _Tp*
template <class _Tp>
struct iterator_traits<const _Tp*>
{
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
看了了么?这就是模板偏特化,与模板特化的区别在于,模板特化以后,实际上其本身已经不是templatized,而偏特化,仍然带有templatized。我们来看一个实际的例子:
#include <iostream>
using namespace std;
// 一般化设计
template <class T, class T1>
class TestClass
{
public:
TestClass()
{
cout<<"T, T1"<<endl;
}
};
// 针对普通指针的偏特化设计,注意偏特化模板类在创建对象时使用的语法。
template <class T, class T1>
class TestClass<T*, T1*>
{
public:
TestClass()
{
cout<<"T*, T1*"<<endl;
}
};
// 针对const指针的偏特化设计
template <class T, class T1>
class TestClass<const T*, T1*>
{
public:
TestClass()
{
cout<<"const T*, T1*"<<endl;
}
};
int main()
{
TestClass<int, char> obj;
TestClass<int *, char *> obj1;
TestClass<const int *, char *> obj2;
return 0;
}
对于输出结果,我这里就不写了,大家可以试一试。
特化与偏特化的调用顺序
对于模板、模板的特化和模板的偏特化都存在的情况下,编译器在编译阶段进行匹配时,是如何抉择的呢?从哲学的角度来说,应该先照顾最特殊的,然后才是次特殊的,最后才是最普通的。编译器进行抉择也是尊从的这个道理。从上面的例子中,我们也可以看的出来,这就就不再举例说明。
总结
对于模板的特化和偏特化,我的理解可能也不是很正确。希望大家和我进行探讨。我这里只是对自己的一些理解进行了总结。最后,也希望大家对我的博客提出中肯的建议。我坚信,分享使我们更进步。
转载于:https://my.oschina.net/ray1421/blog/714093
C++模板之特化与偏特化详解相关推荐
- 第十天2017/04/21(2、泛型编程:模板 / 全特化、偏特化)
1.什么是模板? template<class T1,class T2,.....> 类属----类型参数化,又称参数模板使得程序可以从逻辑功能上抽象,把被处理的对象(数据)的类型作为参数 ...
- 模板特化,全特化,偏特化,全部特化,部分特化的含义
模板特化,任何针对模板参数进一步进行条件限制设计的特化版本.<泛型思维> 全特化就是全部特化,即针对所有的模板参数进行特化.<c++ primer> 偏特化就是部分特化,即针对 ...
- (函数/类模板)的(偏特化/全特化)
特化的概念 特化,就是将泛型的东东搞得"具体化"一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰或完全被指定了下 ...
- C/Cpp / STL / 模板全特化和偏特化
栗子 #include <iostream>template <typename T1, typename T2> struct Test {void Print() { st ...
- [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)
http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1. 主版本模板类 首先我们来看一段初学者都能看 ...
- 【C++模板】特化与偏特化 template [partial] specialization
1 template specialization 模板特化 一般情况下类模板定义如下: template<class Window, class Controller> class Wi ...
- C++——模板特化和偏特化
1.引言 C++中的模板分为类模板和函数模板,虽然它引进到C++标准中的时间不是很长,但是却得到了广泛的应用,这一点在STL中有着充分的体现.目前,STL在C++社区中得到了广泛的关注.应用和研究.理 ...
- C++ 模板的全特化与偏特化
模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的. 模板分为类模板与函数模板,特化分为全特化与偏特化.全特化就是限定死模板实现的具体类型,偏特化就是如果这 ...
- Th4.6:模板全特化、偏特化(局部特化)详述
本小节回顾的知识点分别是模板全特化.偏特化(局部特化). 今天总结的知识分为以下4个大点: (1)特化与泛化 (2)类模板特化 (2.1)类模板全特化 a)常规全特化 ...
最新文章
- 共享文件迁移(fileserver)——从windows server 2003到windows server 2008
- MATLAB读取一张RGB图片转成YUV格式
- 算法测试—机器学习算法评价指标
- 3.20学习内容,字符串与列表
- Python的特殊成员
- HBase的基础知识
- 程序员的算法课(2)-排序算法
- pythonmatplotlib绘图小提琴_使用seaborn制图(小提琴图)
- python地理数据处理库geopy
- 全球及中国锗行业发展规模与前景调查分析报告2022-2028年
- 激光计算机的基本原理和特点,3D激光传感器的原理及特点
- 课得在线:Java程序员未来前景?大龄程序员出路在何方
- 欢迎你、某某某同学python_python123第一周作业
- <C++>初识多态,剖析virtual关键字
- 微信文件夹的dat文件怎么打开_微信dat后缀的文件怎么打开
- pytest-捕获告警信息
- Joel在耶鲁大学的演讲
- Mysql索引、命令重点介绍
- ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)的解决方法。
- Redis AKF CAP 集群知识