【问题标题】:Is this-> mandatory to access Base<T> identifiers from derived classes?this-> 是否必须从派生类访问 Base<T> 标识符?
【发布时间】:2017-11-09 01:27:53
【问题描述】:

此代码使用 MSVC 2015 编译,但不能使用 Clang 5.0.0(主干 304874)编译:

template <typename T>
struct Base
{
  T data;
};

template <typename T>
struct Derived : Base<T>
{
  auto getData() const
  {
    return data;
  }
};

data 替换为Derived::getdata() 中的this-&gt;data 会让Clang 高兴。

根据 C++ 标准,哪个编译器是正确的?

必须在模板代码中使用this-&gt; 才能访问基类的标识符吗?

【问题讨论】:

  • msvc 显然是错误的。 data 是从属名称。
  • clang 正确,msvc 错误。
  • MSVC 在两阶段查找规则方面被破坏了,其中包括依赖名称。
  • 带有 /permissive- 开关的 MSVC 2017 会为此代码发出错误“C2065: 'data': undeclared identifier”。

标签: c++ templates inheritance language-lawyer name-lookup


【解决方案1】:

Clang 是正确的。

$17.6.2/3 Dependent names [temp.dep]

在类或类模板的定义中,在非限定名称查找期间,无论是在类模板或成员的定义点还是在类模板或成员的实例化期间,都不会检查依赖基类的范围。

对于return data;data不合格,则将采用不合格名称查找。这意味着不应找到基类Base&lt;T&gt; 中的名称(这是一个依赖基类,因为它依赖于模板参数T);即不依赖的名称不在依赖的基类中查找。

this-&gt;dataBase&lt;T&gt;::data 使其合格。这意味着将在实例化时查找名称,届时将知道必须探索的确切基础特化。

【讨论】:

  • this-&gt;data 不是限定名称。
  • 还是错了。 “限定名”和“从属名”不可互换。事实上,它们是相互排斥的。
  • @T.C.我糊涂了;所以我不能说name 是非依赖名称或this-&gt;data 是依赖名称?那么这些名称的正确描述应该是什么?或者我只能说他们是qualifiedunqualified? (但不是qualified name 等?)请告诉我,如果我在基本答案上错了,还是术语问题?
  • 基本正确,是术语。 “从属名称”在标准中有一个非常狭窄和具体的定义(它粗略地指的是在实例化上下文中受 ADL 约束的函数名称)。在这里,关键是其他两种形式绕过了您引用的规则,因为它们都没有使用不合格的查找。 this-&gt;data 使用类成员访问查找,Base&lt;T&gt;::data 使用限定查找。
【解决方案2】:

是的,是的。基本上data 取决于T

有一种称为两阶段查找的机制。非(模板)依赖的名称会立即解析 - 在 定义 处。你的data 还不存在,因为Base&lt;T&gt; 还不存在,因为它没有实例化。因此,它抱怨找不到data

你需要提示编译器data依赖于模板,并且名称查找应该在第二阶段进行,在模板参数被替换之后,即模板类被实例化。这可以通过使用this 或提供模板相关范围来完成。

所以,this-&gt;f()Base&lt;T&gt;::f() 都可以。

【讨论】:

    猜你喜欢
    • 2017-11-29
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    相关资源
    最近更新 更多