typename

維基百科,自由的百科全書
跳至導覽 跳至搜尋

"typename"是一個C++程序設計語言中的關鍵字。當用於泛型編程時是另一術語"class"的同義詞[1]這個關鍵字用於指出模板聲明(或定義)中的非獨立名稱(dependent names)是類型名,而非變量名。以下是對於泛型編程typename兩種迥然不同的用法的解釋。

class關鍵字的同義詞[編輯]

這是一項C++程式語言的泛型編程(或曰「模板編程」)的功能,typename關鍵字用於引入一個模板參數,例如:

// 定义一个返回参数中较大者的通用函数
template <typename T>
const T& max(const T& x, const T& y)
{
  if (y < x) {
    return x;
  }
  return y;
}

這種情況下,typename可用另一個等效的關鍵字class代替,如下代碼片段所示:

// 定义一个返回参数中较大者的通用函数
template <class T>
const T& max(const T& x, const T& y)
{
  if (y < x) {
    return x;
  }
  return y;
}

以上兩段代碼沒有功能上的區別。

類型名指示符[編輯]

考慮下面的錯誤代碼:

template <typename T>
void foo(const T& t)
{
   // 声明一个指向某个类型为T::bar的对象的指针
   T::bar * p;
}

struct StructWithBarAsType {
   typedef int bar;
};

int main() {
   StructWithBarAsType x;
   foo(x);
}

這段代碼看起來能通過編譯,但是事實上這段代碼並不正確。因為編譯器並不知道T::bar究竟是一個類型的名字還是一個某個變量的名字。究其根本,造成這種歧義的原因在於,編譯器不明白T::bar到底是不是「模板參數的非獨立名字」,簡稱「非獨立名字」。[2]注意,任何含有名為「bar」的項的類T,都可以被當作模板參數傳入foo()函數,包括typedef類型、枚舉類型或者變量等。

為了消除歧義,C++語言標準規定:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

意即出現上述歧義時,編譯器將自動默認bar為一個變量名,而不是類型名。所以上面例子中的代碼 T::bar * p 會被解釋為乘法,而不是聲明p為指向T::bar類型的對象的指針

如果還有另一個名為StructWithBarAsValue類型,如下:

struct StructWithBarAsValue {
    int bar;
};

那麼,編譯器將以完全不同的方式來解釋

T::bar * p

的含義。

解決問題的最終辦法,就是顯式地告訴編譯器,T::bar是一個類型名。這就必須用typename關鍵字,例如:

template <typename T>
void foo(const T& t)
{
   // 声明一个指向某个类型为T::bar的对象的指针
   typename T::bar * p;
}

這樣,編譯器就確定了T::bar是一個類型名,p也就自然地被解釋為指向T::bar類型的對象的指針了。

參考文獻[編輯]

  1. ^ C++ Primer 4th Edition, 模板和泛型編程,模板定義
  2. ^ http://pages.cs.wisc.edu/~driscoll/typename.html