模板是泛型编程的基础,通过模板可以编写与类型无关的代码,可以提高代码复用
模板分为函数模板和类模板
函数模板相当于一个函数族,编写一个函数模板,然后编译器根据这个模板对不同的参数类型生成不同的函数,
另外一种是类模板,其类成员是模板类型,在调用时通过,显示调用的方法实例化该类型
模板分为非类型模板参数,和类型模板参数
类型模板参数就是在传递时需要传递一个类型,而非类型模板参数就是在模板参数中可以出现一个常量,然后在类模板或者在函数模板中将该参数当常量处理,需要注意的是,非类型模板参数不能使用字符串,浮点型,并且必须在编译期间确定结果。
模板的特化
模板特化是因为,对于有些类型使用模板函数,或者模板类的那种处理方式有问题,于是就对该类型重新写一种处理方式
函数模板的特化,函数模板特化是,在template后面跟上空的<>然后再函数名后跟上需要特化的类型,
template <class T1, class T2>
void func(T1 & a, T2 & b)
{
cout << "template <class T1, class T2>" << endl;
cout << a << " " << b << endl;
}
template<>
void func<int, float>(int & a, float &b)
{
cout << "template<>" << endl;
cout << a << " " << b << endl;
}
类模板的特化分为两种,全特化和偏特化
全特化就是将模板参数表中的所有参数全部确定化,
偏特化同样分两种,一种是部分特化,将一部分参数确定化,另一种是对模板参数进一步的限制,如将模板添加上指针类型,或者添加引用等,
类型萃取
类型萃取是类模板特化的一个应用
//表示内置类型
struct TrueType
{
static bool Get()
{
return true;
}
};
//表示自定义类型
struct FalseType
{
static bool Get()
{
return false;
}
};
template<class T>
struct TypeTraits
{
typedef FalseType IsPodType;
};
//对所有内置类型进行特化
template<>
struct TypeTraits<int>
{
typedef TrueType IsPodType;
};
template<>
struct TypeTraits<short>
{
typedef TrueType IsPodType;
};
//....
//对所有内置类型特化完后所有内置类型在调用时均会调用
//特化后的类型,所有is_POD_type均被定义成_true_type
//所有自定义类型,均通过编译器实例的类模板定义成false_type
//然后根据类型调用相对的类中Get函数确定需要使用的方法
template<class T>
void Copy(T* dst, const T* src, size_t size)
{
if (TypeTraits<T>::IsPodType::Get())
{
cout << "memcpy" << endl;
memcpy(dst, src, sizeof(T)*size);
}
else
{
cout << "for" << endl;
for (size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
}