2012-02-03 24 views
1

我在這個網址如果T是一個模板參數,T :: x(y)語句是如何模糊的?

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_typename.htm

讀取事實表,我意識到,我不知道什麼類型的T :: X可能代表可能。下面是摘錄

template<class T> class A 
{ 
    T::x(y); 
    typedef char C; 
    A::C d; 
} 

聲明T :: X(Y)是模糊的。它可能是一個調用函數x() 與非本地參數y,或者它可能是一個變量y 類型T :: x的聲明。 C++將把這個語句解釋爲一個函數調用。 爲了使編譯器將此語句解釋爲 聲明,您需要將關鍵字typename添加到它的開頭 。聲明A :: C d;是不合格的。 A類也指 A,因此取決於模板參數。您必須在 關鍵字類型名稱添加到這個聲明的開頭:

我想了解如何有可能是類型T :: x的變量y,怎麼會變成這樣的工作,有什麼能這可能意味着什麼? x會是什麼?

感謝:-)

回答

6

作爲熱身到我的完整的答案,考慮以下因素:

template <typename T> void IterateOverContainer(T container) { 
    /* Error! */ 
    T::iterator itr(container.begin()); 
} 

這裏,iterator是嵌套的T內部的類型;例如,std::vector<int>::iterator。爲了避免歧義這裏,typename關鍵字成爲必要:

template <typename T> void IterateOverContainer(T container) { 
    /* Now good! */ 
    typename T::iterator itr(container.begin()); 
} 

現在,這是「明確」一類的名稱(這是typename手段!),所以很明顯,我們要聲明一個變量,而不是通話一個函數。

這就是說,新的C++ 11層的功能,你可以用auto完全迴避這個問題:

template <typename T> void IterateOverContainer(T container) { 
    auto itr(container.begin()); 
} 

,或者更明確:

template <typename T> void IterateOverContainer(T container) { 
    auto itr = container.begin(); 
} 

現在,你的問題:如何可以T::x(y)曾經聲明一個變量?好了,由於到C的一個奇怪的怪癖,這是一個完全合法的變量聲明:

int (x); 

這是一樣

int x; 

因此,如果我們有這樣的事情:

template <typename T> void IterateOverContainer(T container) { 
    /* Error! */ 
    T::iterator(itr); 
} 

這可以解釋爲T::iterator類型的名爲itr的變量的聲明,或者作爲對函數T::iterator的呼叫通過itra是一個參數。 typename的使用消除了它是哪一個。

有趣的是,這個額外括號的規定與Most Vexing Parse存在的原因相同。我希望你永遠不會遇到它。 :-)

希望這有助於!

+0

看起來像你的帳戶是爲了回答這個問題:) – 2012-02-03 03:50:37

+0

只是幾個簡單的問題,如果我在另一個內部定義一個類(x內部的Y)這將是類型Y :: x?我認爲小寫字母x是把我扔掉的東西,我沒有意識到這是一個嵌套類,如果它是什麼。也是T :: iterator itr(container.begin()); 構建一個類型,如何解釋? Sry因爲我對這個話題的無知 – rubixibuc 2012-02-03 03:53:00

+0

@ rubixibuc-(請注意,在我收到這條消息之前,我已經更新了我的答案,所以你可能想閱讀結束我的編輯)。我不確定我是否通過「構建一個類型」來獲得你的意思。你能澄清嗎? – templatetypedef 2012-02-03 03:54:44

0

如已經陳述的,T::x可以指「該x類型(可能是一個或classtypedef),其內T定義。它也可以指」一個指針T的成員函數x

編譯器通常可以根據某些線索找出哪個是正確的(您是否寫過T::x foovoid (T::*)() foo = T::x?); Visual Studio,和GCC曾經(他們停下來,因爲當時,人們會讓他們的代碼在GCC上編譯,但不在Visual Studio上編譯)。該標準要求typename消除疑難案件。

相關問題