偏特化就是部分特化。
利用模版的偏特化,可以实现一些类型过滤。
比如,我想让一个类模版指定类型如int能编译过,其他编译不过,代码实现如下:
template <typename T>
class A;
template<>
class A<int>
{
};
int main()
{
A<int> a;
A<double> b; //error
return 0;
}
以上代码,通用的模版没有实现,只实现了int的特化模版,这样class A就只接受int类型的模版形参了。
同理,我们也能实现让指定类型如int不能编译过,其他都能编译过,代码如下:
template <typename T>
class A
{};
template<>
class A<int>;
int main()
{
A<int> a; //error
A<double> b;
return 0;
}
函数模版比类模版多了一个参数传入的过程,所以可以省略模版参数,因为可以从传入的参数推导。比如:
#include<iostream>
using namespace std;
template< typename T>
int func(T a, T b)
{
cout << a + b << endl;
return a + b;
}
int main()
{
func<int>(3, 4);
func(3, 4);
return 0;
}
func<int>(3, 4);和func(3, 4);调用是等价的。
关于函数模版可以推导,这里有一个有趣的问题:
如果要实现一个类型转化的模版,如下两种定义,那种比较好?
template<typename Dst, typename Src> Dst convert(Src src)
template<typename Src, typename Dst> Dst convert(Src src)
这两种定义的差别主要在于模版形参,从直觉上看,从src转化到dst,可能第二种定义更符合我们的逻辑,但是第一种定义,更能方便函数模版的调用者—— i = Convert<int>(7.04); ,不需要像这样写完整的模版形参—— i = Convert<int, double>(7.04); ,尽管他们是等价的。
这个例子告诉我,对待别人要宽——让用户更方便的使用。
写到这里,又想起一个例子,跟C++模版没关系:
我们作为开发,在一个类中实现"<"的重载时,也要实现">"和“==”的重载,因为调用者会觉得,既然有了"<"操作,那么“==”和“>”自然也有。
然而,我们作为一个类的使用者时,尽可能少使用重载方法,采用一个"<"就能满足比较操作。这样,即使程序员没有实现所有比较符号的重载,我的代码也能正常运行。
这又是一个对自己要严格,对别人要宽泛的例子。
来源:oschina
链接:https://my.oschina.net/u/1453800/blog/210176