Iter , Iter); private: template
void copy_elems(Iter, Iter); }
在类模板的外部定义模板成员,必须包含类模板的形参和模板成员的模板形参:
template
//类模板的形参
tmeplate
//成员模板形参 void Queue
::assign(Iter begin, Iter end) { ... }
与其他成员一样,成员模板也只有在被使用的时候才会实例化。
类模板的static成员
template
class Bar
{
public:
static std::size_t count(){return ctr};
private:
static std::size_t ctr;
}
实例化原则是:相同类型的实例共享一个static成员,例如Bar 类型的实例共享一个static 成员ctr,Bar 类型的实例共享一个static成员ctr;
- 使用方法
Bar
bar1, bar2;
size_t ct = Bar
::count();
初始化方法
template
size_t Foo
::ctr = 0;
模板特化
由于模板的定义中,其操作都是依赖实例化的类型是否支持该操作或者操作的结果与预期是否相匹配,例如:
template
int compare(const Type& t1, const Type &t2)
{
if(t1 > t2) return 1;
if(t1 < t2> return -1;
return 0;
}
在上面的例子中,如果用char* 去实例化模板时,函数将比较两个指针,很明显与预期的记过不相吻合。此时可以通过模板特例话来解决。
函数模板特化
函数模板特例化形式如下:
- 关键字template 后面接一对空的尖括号(<>);
- 在接末班吗和一堆尖括号,尖括号中制定这个特化定义的模板形参;
- 函数形参表;
- 函数体。
例如:
template <>
int compare
(const char *t1, const char *t2)
{
return strcmp(t1, t2);
}
如果有多个模板形参,则依次排列即可。
类模板特化
定义类特化
template <>
class Queue
{
...
}
需要在类特化的外部定义普通成员函数时,成员之前不能加 template<>标记:
void Queue
::push(const char* val)
{
...
}
特化成员而不特化类
template <>
void Queue
::push(const char* const &val)
{
...
}
template<>
void Queue
::pop() { ... }
现在,类类型Queue
template
class tem
{
...
};
//partial specialization :fixes T2 as int and allows T2 to vary.
template
class tem
{ }
使用方法:
tem
foo; //调用普通的类模板
tem
bar; //调用偏例化版本
重载与函数模板
函数模板可以重载:可以定义有相同名字但形参数据或类型不同的多个函数模板, 也可以定义与函数模板有相同名字的普通非模板函数。
不过从实践来看,设计既包含函数模板又包含非模板函数的重载函数集合是困难的,因为坑你会使函数的用户感觉到奇怪,定义函数模板特化几乎总是比使用非模板版本更好。