1. 程式人生 > >C++進階--模板及關鍵字typename

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是一個特殊的名稱空間,我們不能更改它的內容,但是可以為我們的型別提供特化的版本