C++进阶--模板及关键字typename

//############################################################################
/*
 *  模板介绍
 */
//函数模板
template<typename T>
T square(T x) {
   return x*x;
}

//类模板
template<typename T>
class BoVector {
   T arr[1000];
   int size;
public:
   BoVector():size(0) {}
   void push(T x) { arr[size] = x; size++; }
   T get(int i) const { return arr[i]; }
   int getSize() const { return size; }
   //void print() const {for(int i=0; i<size; i++) {cout << arr[i] << endl;}}
   void print() const { 
      const int* p = arr; 
      for(int i=0;  i<size; i++) {cout << *(p++) << endl;}
   }
};

template<typename T>
BoVector<T> operator*(const BoVector<T>& rhs1, BoVector<T>& rhs2) {
   BoVector<T> ret;
   for (int i=0; i<rhs1.getSize(); i++) {
      ret.push(rhs1.get(i)*rhs2.get(i));
   }
   return ret;
}

int main()
{
   cout << square(5) << endl;

   BoVector<int> bv;
   bv.push(2);
   bv.push(5);
   bv.push(8);
   bv.push(9);
   bv.print();

   cout << "Print squared bv: " << endl;
   bv = square(bv);
   bv.print();
}


//############################################################################
/*
 *  函数模板类型省略
 */

template<class T>
void f() {
   ...
}

int main() {
   f<int>();  // T显式指定
}


// 类型T可以省略
template<class T>
void f(T t) {
   ...
}

int main() {
   f(67);  // 编译将其绑定为int型

   f<long>(67);  // 显示告诉编译器为long类型

   f(67L);
}



//############################################################################
/*
 * 关键字typename及其用法
 */

template<class T>
void printAge(T& item) {
   ...
}

template<typename T>
void printAge(T& item) {
   ...
}

//用于模板参数两者等效
//使用typename更易理解
//



/*
 * Dependent Type 取决于模板参数的类型
 */
template<typename T> A {
   vector<T> vec;
}

/*
 * Nested Dependent Type  包含在某个类里的dependent type
 */
template<typename T> A {
   T::age myAge = 9;
   vector<T>::iterator itr;
}



/*
 * typename 用法二
 */
class Dog {
   public:
   typedef int age;
};

template<class T>
void printMyAge(T& item) {
   int n = 9;
   T::age* a = &n;
   cout << (*a) << endl;
}

int main() {
   Dog d;
   printMyAge<Dog>(d);    
}


// 上面的代码编译不过,T::age是类型,编译器当成变量

//class Wolf {
//   public:
//   int age;
//}; 


/*
 * 法则: 当使用嵌套依赖类型的时候总是在前面加上typename,告诉编译器这是类型
 */



// 例外: 在基类列表或者初始化列表中

template<typename T>
class D : public T::NestedBaseClass {
public:
   D(int x) : T::NestedBaseClass(x) { 
      typename T::NestedBaseClass y;
      ...
   }
}


//############################################################################
/*
 *  模板特化和偏特化
 */
// std是一个特殊的命名空间,我们不能更改它的内容,但是可以为我们的类型提供特化的版本

猜你喜欢

转载自www.cnblogs.com/logchen/p/10182696.html