問題描述
考慮這個代碼,
template<class T>
struct Sample
{
typename T::X *x; //declare pointer to T's X
};
在上面的代碼中,關鍵字typename
是編譯器所必需的,以便它可以在模板中消除嵌套類型和嵌套值之間的歧義.這意味著,在沒有 typename
關鍵字的情況下,編譯器會將其解釋為 T::X 與 x 的乘法,
In the above code, the keyword typename
is required by the compiler, so that it can disambiguate between nested types and nested values in templates. That means, in the absence of typename
keyword, compiler would interpret this as multiplication of T::X with x,
T::X *x; //multiply T::X with x
因此在可能出現歧義的情況下,關鍵字typename
變成了necessity 以消除歧義.但是,上下文本身消除歧義的情況很少.其他主題討論了基類和函數的上下文-參數(盡管后者不會消除歧義).在這個話題中,我特別想討論另外兩個看起來無歧義的上下文,但我們仍然需要寫typename
,
So in such situations where ambiguity can arise, the keyword typename
becomes necessity so as to remove ambiguities. But there are few situations when the context itself removes ambiguities. The other topic discusses contexts of base-class and function-parameters (the latter doesn't remove ambiguity though). In this topic, I particularly want to discuss other two contexts which seem to be unambiguous, but we're still required to write typename
,
typedef typename T::X xtype;
pX = new typename T::X;
在這兩種情況下,關鍵字typedef
和new
足以讓編譯器清楚地知道接下來是type, 不是 價值.
In these two situations, the keywords typedef
and new
make it clear enough to the compiler that whatever follows is type, not value.
所以我的問題是,為什么編譯器仍然需要 typename
關鍵字,即使在明確的情況下,例如當我們使用 typedef
和 new
時?
So my question is, why do compilers still need the typename
keyword, even in unambiguous situations such as when we use typedef
and new
?
//typedef NOT followed by a type!
int typedef A;
這種語法要求我稍微修改我的問題,以便其他人可以看到我試圖提出的觀點.
This syntax asks me to modify my question a little bit, so that the point which I'm trying to make, may be seen by others.
考慮一下,
T::X typedef *x;
所以從上下文來看,編譯器仍然很清楚 T::X 是一種類型,無論它出現在 before typedef
還是 在 typedef
之后.除非C++允許我們寫typedef 5 5
或typedef T::value t_value
(其中T::value是value),typedef
本身的存在消除了所有歧義,因此,typename
似乎是標準不必要的要求(在這種情況下).同樣的論點也適用于 new
.
So from the context, it's still clear enough to the compiler that T::X is a type, no matter whether it appears before typedef
,or after typedef
. Unless C++ allows us to write typedef 5 five
or typedef T::value t_value
(where T::value is value), the presence of typedef
itself removes all ambiguities and so, typename
seems to be an unnecessary requirement by the Standard (in such situations). Same argument holds true for new
as well.
另外,我寫了一個類模板,它使用這個結構作為模板參數:
Also, I've written a class template which is using this struct as template argument:
struct A
{
struct X { string name; };
static const int X = 100;
};
我特別想知道以下代碼(來自構造函數)是否正確(可移植),
I particularly want to know if the following code (from the constructor) is correct (portable) or not,
//two interesting statements
pX = new typename T::X; //T::X means struct X
product = T::X * p; //but here, T::X means int X
完整代碼位于 ideone 此處.回復之前請先看一下.:-)
The complete code is here at ideone. Please have a look at it before replying. :-)
推薦答案
C++ 語法比這更瘋狂.
C++ syntax is more crazy than that.
// typedef NOT followed by a type!
int typedef A;
// new NOT followed by a type!
new (0) int;
其他人對您的示例發表了評論.typename
說明符不會忽略非類型名稱進行查找.所以如果你說new typename T::X
,并且T
中有一個對象名X
,它仍然會被找到而不是類型名稱 X
(然而,GCC 在查找 typename
之后的名稱時會忽略非類型名稱.但這不符合標準).
Others have commented about your example. The typename
specifier does not yield to lookup ignoring non-type names. So if you say new typename T::X
, and there is an object name X
in T
, it will still be found instead of the type name X
(GCC however ignores non-type names in looking up a name after a typename
. But that's not Standards compliant).
對編輯的回答:
考慮一下,
T::X typedef *x;
所以從上下文來看,無論是出現在 typedef 之前,還是出現在 typedef 之后,編譯器仍然很清楚 T::X 是一種類型.
So from the context, it's still clear enough to the compiler that T::X is a type, no matter whether it appears before typedef,or after typedef.
編譯器必須知道聲明說明符和(即類型部分"和聲明符部分何時開始(即名稱"部分).有些聲明類型部分為空:
The compiler has to know when the declaration specifiers and (i.e the "type section" and when the declarator section start (i.e the "names" section). There are declarations where the type section is empty:
// constructor definitions don't need a type section
MyClass::MyClass() { }
// conversion function definitions don't need a type section
MyClass::operator int() { }
如果您指定的名字不是類型,則類型部分結束,名稱部分開始.說 T::X
告訴編譯器:
If the first name you specify is not a type, the type section ends, and the name section starts. Saying T::X
tells the compiler:
現在我想定義T::X
.
它從左到右讀取,所以當它遇到typedef
時它會認為你忘記了分號.在類內部,解釋略有不同,但也很相似.這是一個簡單而有效的解析.
It reads from left to right, so it will think you forgot a semicolon when it then encounters the typedef
. Inside classes the interpretation is slightly different but much like this too. That's a simple and effective parse.
同樣的論點也適用于 new.
Same argument holds true for new as well.
我傾向于同意你的看法.從語法上講,如果省略括號應該是明確的.由于我從未編寫過 C++ 解析器,因此可能存在我沒有看到的隱藏陷阱.
I tend to agree with you here. Syntactically it should be unambiguous if you leave off parentheses. As I've never written a C++ parser, there may be hidden pitfalls I'm not seeing, though.
在諸如 new
這樣的語言的極端情況下,每次添加 typename
都可能需要為編譯器和標準編寫者進行大量的設計,同時仍然需要 typename
用于絕大多數其他需要它的情況.我不認為這是值得的.
Every addition of typename
in corner cases of the language like in new
will potentially require substantial amount of design for both compilers and standards writers, while still requiring typename
for the vast majority of other cases where it's needed. I don't think that this pays off.
這篇關于在 typedef 和 new 中使用 typename 關鍵字的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!