为什么关键字“typename"是需要在限定的从属名

时间:2023-04-24
本文介绍了为什么关键字“typename"是需要在限定的从属名称之前,而不是在限定的独立名称之前?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..
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::iterators 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::AFoo::BFoo::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::AT::BT::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是否可以转换为intax是否可以乘以,以及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模板网!

上一篇:类模板上的运算符重载 下一篇:C++:如何要求一种模板类型派生自另一种模板类型

相关文章

最新文章