
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
非类型模板参数的声明方式如下:
template <typename T, int N>
class ClassName {
// 类成员
};其中,int N 是一个非类型模板参数,表示一个整数。
非类型模板参数可以是以下类型:
int、long、unsigned int 等)但需要注意的是,非类型模板参数的值必须在编译时是已知的常量(即编译时常量表达式)。
类型安全
float、double),但可以是整数类型或指针类型。模板特化(Template Specialization)是C++模板机制中一个非常重要的特性。它允许程序员为特定的模板参数提供专门的实现,而不是使用模板的一般定义。模板特化可以用于函数模板和类模板,用于处理某些特殊类型或参数时提供更优化或更合适的实现。 通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
模板特化分为两种:
函数模板的特化通常只能是全特化,因为函数模板的参数不能部分指定。
template <>
返回类型 函数名(参数列表) {
// 特化版本的实现
}函数模板的特化步骤:
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。类模板的特化可以是全特化,也可以是偏特化。
全特化为模板的所有参数提供具体的类型或值,从而提供一个完全不同的实现。
template <>
class 类名<特化参数列表> {
// 特化版本的成员
};偏特化是指仅对模板的部分参数进行特化,而其他参数保持通用。偏特化只能用于类模板,不能用于函数模板。
template <typename T1, typename T2>
class 类名<T1, 特化参数> {
// 偏特化版本的成员
};偏特化有以下两种表现方式:
xxx<int> 和 xxx<int>,也不能定义两个冲突的偏特化版本。什么是分离编译 :
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
在C++中,模板的定义和实例化通常是分开的:
.h 或 .hpp)中。由于模板的实例化需要知道模板的具体参数类型,因此模板的定义必须在编译时对所有可能的实例化可见。这导致模板代码通常不能像普通函数或类那样直接分离编译。
.cpp)都会重新实例化模板,导致重复编译。显式实例化是指在源文件中显式地指定模板的实例化类型。这样可以将模板的实例化代码集中到一个编译单元中,从而减少重复编译和代码膨胀。
// 在源文件中显式实例化模板
template class TemplateName<SpecificType>;优点:
缺点:
将模板的定义和声明分开,定义放在源文件中,声明放在头文件中。这种方法在C++中通常不推荐,因为模板的定义必须对所有可能的实例化可见。
优点:
缺点:
将模板的定义和声明全部放在头文件中,这样可以确保模板的定义对所有编译单元可见。这种方法是最常用的解决方案,但会导致编译时间增加和代码膨胀。
优点:
缺点:
模板的分离编译是一个复杂的问题,主要原因是模板的实例化依赖于具体的类型参数。以下是几种解决模板分离编译问题的方法的总结:
优点
缺陷