Is this-> mandatory to access Base<T> identifiers from derived classes?
Asked Answered
F

2

27

This code compiles with MSVC 2015, but doesn't compile with Clang 5.0.0 (trunk 304874):

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

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

Replacing data with this->data in Derived::getdata() makes Clang happy.

Which compiler is correct according to the C++ standard?

Must this-> be used in template code to access an identifier of a base class?

Freudberg answered 7/6, 2017 at 15:29 Comment(4)
msvc is wrong, obviously. data is a dependent name.Hedley
clang is correct, msvc is wrong.Mosra
MSVC is broken with regards to the two-phase-lookup rules, which include dependent names.Cog
MSVC 2017 with the /permissive- switch emits the error "C2065: 'data': undeclared identifier" for this code.Intelligencer
V
27

Clang is correct.

$17.6.2/3 Dependent names [temp.dep]

In the definition of a class or class template, the scope of a dependent base class is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

For return data;, data is unqualified, then unqualified name lookup will be employed. This means the name in the base class Base<T> (which is a dependent base class because it depends on the template parameter T) shouldn't be found; i.e. the non-dependent names are not looked up in dependent base classes.

this->data or Base<T>::data makes it qualified. This means the name will be looked up at the time of instantiation, and at that time the exact base specialization that must be explored will be known.

Virgo answered 7/6, 2017 at 15:51 Comment(5)
this->data is not a qualified name.Noxious
Still wrong. "qualified name" and "dependent name" are not interchangeable. In fact, they are mutually exclusive.Noxious
@Noxious I'm confused; so I can't say name is non-dependent name or this->data is dependent name ? Then what should be the correct description for these names? Or I can only say they're qualified or unqualified? (but not qualified name etc?) Please tell me if I'm wrong at the basic of the answer, or is it a term issue?Virgo
The basics is correct, it's the terminology. "dependent name" has a very narrow and specific definition in the standard (it refers, roughly, to function names subject to ADL in the instantiation context). Here, the point is the other two forms bypass the rule you cited because neither uses unqualified lookup. this->data uses class member access lookup, and Base<T>::data uses qualified lookup.Noxious
@T.C.: The modern (standard) terminology is that data in this->data is a dependent ([temp.dep.type]/5) (member-)qualified ([basic.lookup.qual.general]/2) name.Permanency
A
16

Yes, it is. Basically data depends on T.

There is a mechanism called two-phase lookup. Non-(template)dependent names are resolved immediately - at the point of definition. Your data does not exist yet, because Base<T> does not exist yet, as it was not instantiated. Thus, it complains that data is not found.

You need to hint compiler that data depends on the template, and the name lookup should be performed in the second phase, after template parameters are substituted, i.e. template class was instantiated. This can be done by using this or providing template dependent scope.

So, either this->f() or Base<T>::f() will work.

Accept answered 7/6, 2017 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.