这是否必须从派生类访问Base <T>标识符?

Mr.*_*C64 26 c++ inheritance templates language-lawyer name-lookup

此代码使用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;
  }
};
Run Code Online (Sandbox Code Playgroud)

datathis->datain 替换Derived::getdata()让Clang高兴.

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

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

son*_*yao 27

铿锵是对的.

$ 17.6.2/3从属名称[temp.dep]

在类或类模板的定义中,在类模板或成员的定义点或类模板或成员的实例化期间,在非限定名称查找期间不检查从属基类的范围.

对于return data;,data不合格的,那么不合格的名称查找会被采用.这意味着不应该找到基类中的名称Base<T>(因为它取决于模板参数,它是依赖基类T); 即,非依赖名称不会在依赖基类中查找.

this->dataBase<T>::data使其合格.这意味着将在实例化时查找名称,并且在那时必须知道必须探索的确切基本特化.

  • `this-> data`不是限定名. (2认同)
  • 基础是正确的,这是术语."依赖名称"在标准中具有非常狭窄和特定的定义(粗略地,它指的是在实例化上下文中受ADL约束的函数名称).在这里,重点是其他两种形式绕过了你引用的规则,因为它们都没有使用不合格的查找.`this-> data`使用类成员访问查找,`Base <T> :: data`使用限定查找. (2认同)

luk*_*k32 15

是的.基本上data取决于T.

有一种称为两阶段查找的机制.非(模板)相关名称会立即解析 - 在定义时.你data还不存在,因为Base<T>它还没有实例化,因为它还没有实例化.因此,它抱怨data没有找到.

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

所以,要么this->f()Base<T>::f()将要工作.