模板的编译一般采用包含编译,(其他比较偏门的会介绍export
啥的),export
已经被废止了,所以不再去研究。
正确的做法是:
- 模板的实现都放到
.h
也就是头文件里面
- 使用的时候直接包含头文件
在链接阶段,如果是因为模板生成的代码,比如类定义或者函数义有多份,那么会自动去重。
嵌套类型依赖
假设想使用T
类里面的iterator
,如果代码写做如下:
template<typename T> void print2nd(const T& container) { T::const_iterator * x; ... }
|
由于编译器并不清楚const_iterator
是一个类型,还是静态变量,大多数情况下会认为是一个静态变量
。但是,这里实际上是一个类型,所以这里会编译报错。
那么正确的写法应该是
template<typename T> void print2nd(const T& container) { typename T::const_iterator *x; ... }
|
也就是说,在嵌套类型依赖的时候,需要明确的指出typename
这个类型。
例外
只有2个地方是不需要在嵌套依赖的时候来指明typename
的,那么就是声明继承的时候。
template<typename T> class Derived: public Base<T>::Nested // 1. 这里不需要 { public: explicit Derived(int x) : Base<T>::Nested(x) // 2. 这里也不需要 { typename Base<T>::Nested temp; //nested dependent type, need typename } };
|
比如,这里Nested
就是Base<T>
里面的一个类型。实际上,这里也很明显,那就是继承肯定是继承于类型,而不是一个静态变量。
类中的模板函数
template<typename T> class aTMP{ public: typedef const T reType; }; void f() { std::cout << "global f()" << std::endl; } template<typename T> class Base { public: template<int N = 99> void f() { std::cout << "member f(): " << N << std::endl; } };
|
this指针
this 用于指定查找基类中的成员
- (当基类是依赖模板参数的类模板实例时,由于实例化总是推迟,这时不依赖模板参数的名字不在基类中查找,文献[1]第 166 页)
#include <iostream> template<typename T> class aTMP{ public: typedef const T reType; }; void f() { std::cout << "global f()\n"; } template<typename T> class Base { public: template <int N = 99> void f() { std::cout << "member f(): " << N << '\n'; } }; template<typename T> class Derived : public Base<T> { public: typename T::reType m; Derived(typename T::reType a) : m(a) { } void df1() { f(); } void df2() { this->template f(); } void df3() { Base<T>::template f<22>(); } void df4() { ::f(); } }; int main(){ Derived<aTMP<int>> a(10); a.df1(); a.df2(); a.df3(); a.df4(); std::cin.get(); return 0; }
|