大部分的C++程序员都写过模板。可以说模板是个非常巧妙的东西,它被使用在C++的STL的实现中,也同样经常被用在各种开源代码的底层,更经常被各程序员作为底层代码开发的一个基础。对于模板的概念这里也不再赘述,只阐述模板的巧妙,当然这也只属于个人的理解,可能存在错误,欢迎各同行朋友来指正。
首先先看几行代码:
template<class T , class K = void>
class base_1
{
public:
typedef int INT;
};
template<class T , class K = void>
class base
{
public:
base()
{
printf("11\n");
}
};
template<class T>
class base<T , typename base_1<T>::INT>
{
public:
base()
{
printf("22\n");
}
};
请问一下几行输出结果是什么?为什么?
base<int , float> aaaa1;
base<int , int> aaaa2;
base<int , void> aaaa3;
在上述代码中,模板的定义就用到了几个巧妙的地方:
1. template<class T, class K = void> 在这行声明中,声明了模板的两个类,然而第二个类的默认是void,即在这个模板生命下的base, 可以这么定义对象:base<int, float> 或者base<int>;前者对象声明和后者对象声明是不同的。
2. 在第二个类base的定义中,实际是针对第一个base声明的偏特化(关于偏特化网上有很多资料可以参考,这里不做细致的解释)。而偏特化就是针对需要特殊处理的类型做的特殊处理,也是模板的一个巧妙之处。
如果在上述代码,能够毫不犹豫的说出正确答案,那么下面的代码又做何理解?
#include <type_traits>
#include <iostream>
#include <string>
using namespace std;
template<class t, class enable = void>
class a
{
public:
a()
{
printf("11\n");
}
};
template<class t>
class a<t, typename std::enable_if<std::is_floating_point<t>::value>::type>
{
public:
a()
{
printf("22\n");
}
};
int main()
{
a<float, int> a4;
return 0;
}
对于上述代码应该输出什么,可能很多的第一个答案都是11, 但实际答案是22。这个就是上述模板定义的另一个巧妙之处,重点在于
class a<t, typename std::enable_if<std::is_floating_point<t>::value>::type>
这句定义可以理解为两个定义,当理解这个就不难理解了。一个如下:
template<class t>
class a
{
public:
a()
{
printf("22\n");
}
};
另一个如下:
template<class t>
class a<float, t>
{
public:
a()
{
printf("22\n");
}
};