typename的一些用法和注意問題

2022-09-17 01:51:11 字數 1621 閱讀 4145

一些關鍵概念

在我們揭開真實原因的面紗之前,先保持一點神秘感,因為為了更好的理解c++標準,有幾個重要的概念需要先行介紹一下。

限定名和非限定名

限定名(qualified name),故名思義,是限定了命名空間的名稱。看下面這段**,cout和endl就是限定名:

#include int

main()

cout和endl前面都有std::,它限定了std這個命名空間,因此稱其為限定名。

如果在上面這段**中,前面用using std::cout;或者using namespace std;,然後使用時只用cout和endl,它們的前面不再有空間限定std::,所以此時的cout和endl就叫做非限定名(unqualified name)。

依賴名和非依賴名

依賴名(dependent name)是指依賴於模板引數的名稱,而非依賴名(non-dependent name)則相反,指不依賴於模板引數的名稱。看下面這段**:

template 

struct

myclass ;

因為是內建型別,所以類中前三個定義的型別在宣告這個模板類時就已知。然而對於接下來的三行定義,只有在模板例項化時才能知道它們的型別,因為它們都依賴於模板引數t。因此,t, vector和vector::iterator稱為依賴名。前三個定義叫做非依賴名。

更為複雜一點,如果用了typedef t u; u u;,雖然t沒再出現,但是u仍然是依賴名。由此可見,不管是直接還是間接,只要依賴於模板引數,該名稱就是依賴名。

typename的標記作用:

結束以上兩個個概念的討論,讓我們接著揭開typename的神秘面紗。

乙個例子

在stroustrup起草了最初的模板規範之後,人們更加無憂無慮的使用了class很長一段時間。可是,隨著標準化c++工作的到來,人們發現了模板這樣一種定義:

template 

void

foo()

在上例**中t本身已經是模板的型別引數,它只有等到模板例項化時才會知道是哪種型別,更不用說由t定義的內部的iterator

編譯器不知道第三行**到底是,定義乙個變數還是定義乙個新型別,這樣同一行**能以兩種完全不同的方式解釋,而且在模板例項化之前,完全沒有辦法來區分它們,這絕對是滋生各種bug的溫床。這時c++標準委員會再也忍不住了,與其到例項化時才能知道到底選擇哪種方式來解釋以上**,委員會決定引入乙個新的關鍵字,這就是typename

c++標準定義到:

對於用於模板定義的依賴於模板引數的名稱,只有在例項化的引數中存在這個型別名,或者這個名稱前使用了typename關鍵字來修飾,編譯器才會將該名稱當成是型別。除了以上這兩種情況,絕不會被當成是型別。

因此,如果你想直接告訴編譯器t::iterator是型別而不是變數,只需用typename修飾:

template 

void

foo()

通過加上typename關鍵字,這樣編譯器就可以確定t::iterator是乙個型別,而不再需要等到例項化時期才能確定,因此消除了歧義。

和 的一些用法

是邏輯與運算子,是邏輯或運算子,而且兩個都是短路的,即 和 和 還是不一樣的,和 是短路邏輯與和邏輯或。當計算機執行 時,當 第一條件為false時,就不再判斷我第二條件 當 第一條件為true時,就不再判斷第二條件 所以除了做邏輯判斷的作用外,還可以作條件判斷加賦值,充當某種情況的ifelse使用...

的一些用法

action標籤,顧名思義,是用來呼叫action的標籤,在jsp中頁面中,可以具體指定某一命名空間中的某一action。而標籤的主體用於顯示及渲染actionr的處理結果。action標籤有如下幾個屬性 id 可選屬性,作為該action的引用id name 必選屬性,指定呼叫action nam...

repo 的一些用法和理解

repo的用法 zz wget 或者 curl bin repo 用repo sync 在抓去 android source code 的時候,會經常出現一些錯誤導致 repo sync 中斷,每次都要手動開始。可以用如下的命令,來自動重複 1 while ne 0 do repo sync don...