同名的 typedef 和模板参数

typedef and template parameter with same name

为什么这种情况不正确(合乎逻辑)

template <typename T>
struct Der: public Base
{
    typedef int T;
    T val;
};

,但这种情况是正确的吗?

struct Base
{
    typedef int T;
};

template <typename T>
struct Der: public Base
{
    T val;
};

标准 14.6.1/7 说:

In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each base class which does not depend on a template-parameter (14.6.2), if the name of the base class or the name of a member of the base class is the same as the name of a template-parameter, the base class name or member name hides the template-parameter name (3.3.7).

为什么这里没有歧义?

根据 [temp.local]/6,第一个示例不正确:

A template-parameter shall not be redeclared within its scope (including nested scopes).

然而,在

template <typename T>
struct Der: public Base
{
    T val;
};

T 隐藏在继承自 Base 的名称中 - 正如 引用 所指定的那样。

[..] if the name of the base class or the name of a member of the base class is the same as the name of a template-parameter, the base class name or member name hides the template-parameter name (3.3.7).

即成员val的类型为intDemo.

因为第二个是明确的:

您可能不关心或不知道超类中有 typedev int T,但您刚刚将 T 作为模板参数引入,这清楚地表明您指的是它在 Der.

中使用 T

一般来说,标准试图确保一个类型的含义 给定的范围是相同的。

如果我们假设 typedef 是允许的,那么考虑下面的 val1val2val3 类型?

template <typename T>
struct Der: public Base
{
    void f1() {
      T val1;      // What is the type of 'val1'?
    }

    T val2;        // What is the type of 'val2'?

    typedef int T;

    T val3;        // What is the type of 'val3'?
};

唯一具有模板参数类型 T 的变量是 'val2'.

这是因为标准要求 class 的所有成员对于 f1 都是 "in scope"。这就是为什么成员函数可以引用稍后在 class 主体中定义的成员变量的原因。

同样的问题也可以用 typedef 来证明:

typedef int T;

struct S
{
  T x;
  typedef float T;
  T y;
};

同样,如果这是合法的,那么用于声明 xT 将引用 ::T,而用于 yT将引用 typedef S::T.

ISO 3.3.7/1 下的标准涵盖了这一点:

The following rules describe the scope of names declared in classes.

...

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.