模板相关

模板的实例化

一个模板只有被使用到,才会被实例化,否则不会被实例化。对于一个实例化后的模板来说,未被调用的成员函数将不会被实例化,只有成员函数被使用时,C++标准才要求实例化他们。其原因,有两点:

  • 空间和时间效率的考虑,如果模板类中有100个成员函数,对某个特定类型只有2个函数会被使用,针对另一个特定类型只会使用3个,那么如果将剩余的195个函数实例化将浪费大量的时间和空间。
  • 使模板有最大的适用性。并不是实例化出来的每个类型都支持所有模板的全部成员函数所需要的运算符。如果只实例化那些真正被使用的成员函数的话,那么原本在编译期有错误的类型也能够得到支持。

可以明确的要求在一个文件中将整个类模板实例化:

template class Point3d<float>;

也可以显示指定实例化一个模板类的成员函数:

template float Point3d<float>::X() const;

或是针对一个模板函数:

template Point3d<float> operator+(   
const Point3d<float>&, const Point3d<float>& );

模板错误报告

模板的错误报告,使用模板并遇到错误的大概都深有体会,那就是一个灾难。

模板的名称决议

  • 一开始先要区分两种意义,一种是C++ 标准所谓的“scope of the template definition”,直译就是“定义模板的范围”。另一种是C++标准所谓的“scope of the temlate instantiation”,可以直译为“实例化模板的范围”。

  • 第一种情况:

// scope of the template definition
extern double foo ( double );

template < class type >
class ScopeRules
{
public:
void invariant() {
_member = foo( _val );
}

type type_dependent() {
return foo( _member );
}
// ...
private:
int _val;
type _member;
};
  • 第二种情况:
//scope of the template instantiation  
extern int foo( int );
// ...
ScopeRules< int > sr0;
sr0.invariant();
sr0.type_dependent();

在“scope of the template instantiation ”中 两个foo()都声明在此 scope中。猜猜sr0.invariant() 中调用的是哪个foo()函数,出乎意料,实际调用的是:

extern double foo ( double );

看上去,应该调用:

extern int foo( int );

毕竟,_val 的类型是 int 类型,它们才完全匹配。而 sr0.type_dependent()
中调用的却在我们意料之中,调用的是:

extern int foo( int );

诸上所述,看上去或合理或不合理的选择,原因在于:

  • template 之中, 对于一个非成员名字的决议结果是根据这个 name
    的使用是否与“用以实例化该模板的参数类型”有关来决定name。如果其使用互
    不相干,那么就以“scope of the template dclaration”来决定name。如果其
    使用的互相关联,那么就以“scope of the template
    instantiation”来决定name.