問題描述
class A
{
static int iterator;
class iterator
{
[...]
};
[...]
};
我(認為我)理解這里需要 typename
的原因:
I (think I) understand the reason why typename
is needed here:
template <class T>
void foo() {
typename T::iterator* iter;
[...]
}
但我不明白為什么這里不需要typename
:
but I don't understand the reason why typename
is not needed here:
void foo() {
A::iterator* iter;
[...]
}
誰能解釋一下?
后面編譯器沒有問題的原因,我在評論里發現回答的很好:
The reason why the compiler does not have a problem with the latter, I found to be answered well in a comment:
在 A::iterator
的情況下,我不明白為什么編譯器不會將它與 static int iterator
混淆?- xcrypt
in the case of A::iterator
I don't see why the compiler wouldn't confuse it with the static int iterator
? - xcrypt
@xcrypt 因為它知道 A::iterator
是什么,并且可以根據它的使用方式選擇哪一個 – Seth Carnegie
@xcrypt because it knows what both A::iterator
s are and can pick which one depending on how it is used – Seth Carnegie
編譯器在限定依賴名稱之前需要 typename
的原因在我看來在 Kerrek SB 接受的答案中得到了很好的回答.請務必閱讀對該答案的評論,尤其是 iammilind 的評論:
The reason why the compiler needs typename
before the qualified dependent names, is in my opinion answered very well in the accepted answer by Kerrek SB. Be sure to also read the comments on that answer, especially this one by iammilind:
"T::A * x;,這個表達式對于 T::A 是類型和 T::A 是值的兩種情況都為真.如果 A 是類型,那么它將導致指針聲明;如果A是一個值,那么它會導致乘法.因此一個模板對于2種不同的類型會有不同的含義,這是不可接受的."
"T::A * x;, this expression can be true for both cases where T::A is a type and T::A is a value. If A is a type, then it will result in pointer declaration; if A is a value, then it will result in multiplication. Thus a single template will have different meaning for 2 different types, which is not acceptable."
推薦答案
C++ 中的名稱可以屬于三個不同的實體層:類型、值和模板.
A name in C++ can pertain to three different tiers of entities: Types, values, and templates.
struct Foo
{
typedef int A; // type
static double B; // value
template <typename T> struct C; // template
};
三個名稱 Foo::A
、Foo::B
和 Foo::C
是所有三個不同層的示例.
The three names Foo::A
, Foo::B
and Foo::C
are examples of all three different tiers.
在上面的例子中,Foo
是一個完整的類型,所以編譯器已經知道 Foo::A
等引用了什么.但現在想象一下:
In the above example, Foo
is a complete type, and so the compiler knows already what Foo::A
etc. refer to. But now imagine this:
template <typename T> struct Bar
{
T::A x;
};
現在我們遇到了麻煩:什么是T::A
?如果T = Foo
,則T::A = int
,這是一個類型,一切都很好.但是當 T = struct { static char A;};
,那么T::A
就是一個值,沒有意義.
Now we are in trouble: what is T::A
? if T = Foo
, then T::A = int
, which is a type, and all is well. But when T = struct { static char A; };
, then T::A
is a value, which doesn't make sense.
因此,編譯器要求你告訴它什么T::A
和T::B
和T::C
應該是.如果你什么都不說,它被假定為一個值.如果你說typename
,它是一個類型名,如果你說template
,它是一個模板:
Therefore, the compiler demands that you tell it what T::A
and T::B
and T::C
are supposed to be. If you say nothing, it is assumed to be a value. If you say typename
, it is a typename, and if you say template
, it is a template:
template <typename T> struct Bar
{
typename T::A x; // ah, good, decreed typename
void foo()
{
int a = T::B; // assumed value, OK
T::template C<int> z; // decreed template
z.gobble(a * x);
}
};
二次檢查例如T::B
是否可以轉換為int
,a
和x
是否可以乘以,以及C
是否真的有成員函數gobble
都推遲到你實際實例化模板.但是,名稱是表示值、類型還是模板的規范對于代碼的句法正確性至關重要,必須在模板定義期間立即提供.
Secondary checks such as whether T::B
is convertible to int
, whether a
and x
can be multiplied, and whether C<int>
really has a member function gobble
are all postponed until you actually instantiate the template. But the specification whether a name denotes a value, a type or a template is fundamental to the syntactic correctness of the code and must be provided right there during the template definition.
這篇關于為什么關鍵字“typename"是需要在限定的從屬名稱之前,而不是在限定的獨立名稱之前?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!