2

When inheriting from a template class, I need to prefix all base class members I access in the derived class with this:

template<typename T>
struct X{
   int foo;
   void bar();
};

template<typename T>
struct Y : public X<T> {

   void blub(){
       foo++; // Does not work
       this->foo++; // Fine
       bar(); // Does not work
       this->bar(); // Fine
   }
}

As I was hinted, the reason why you must prefix the members with this has already been answered HERE. So my remaining question is: Is there a way to avoid all the thises? For example, I have a method in the derived class that uses a lot of base class members. The code looks totally cluttered with all the this-> in it. Is there a way to omit these?

Community
  • 1
  • 1
gexicide
  • 38,535
  • 21
  • 92
  • 152
  • 3
    It's explained in a million places on Stack Overflow, just search around for five (more) minutes. – user541686 Aug 20 '14 at 10:46
  • @Mehrdad: I tried to search for my question first. I could not find it. In addition, is there a way to get around it? – gexicide Aug 20 '14 at 10:48
  • Good search keyword: "dependent names" – Angew is no longer proud of SO Aug 20 '14 at 10:48
  • @Angew: Didn't know about these keywords. However, I tried searching for "C++ dependent names" and "template this dependent names" and got no matching results. – gexicide Aug 20 '14 at 10:50
  • @gexicide You can get around it with a `using` declaration. See the canonical ["Where and why do I have to put the “template” and “typename” keywords? "](http://stackoverflow.com/q/610245/1782465). – Angew is no longer proud of SO Aug 20 '14 at 10:50
  • possible duplicate of [Why do I have to access template base class members through the this pointer?](http://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template-base-class-members-through-the-this-pointer) – Constructor Aug 20 '14 at 10:51
  • @Angew: How can it be avoided with `using`? That would be interesting, but I cannot find it in the question you linked. – gexicide Aug 20 '14 at 10:52
  • @Constructor: Interesting, yes, that question explains it. But it does not give a hint whether and how it can be avoided. – gexicide Aug 20 '14 at 10:52
  • 1
    @gexicide Write `using X::foo;` in your `Y` class template. – Constructor Aug 20 '14 at 10:55
  • I have rephrased the question so it only asks how it can be circumvented, not why it is the case. I have added a link to the question that explains why. @Constructor: Interesting, I will try that. You can also phrase it as answer if you want. – gexicide Aug 20 '14 at 10:56

1 Answers1

8

To make this work, you need to turn the non-dependent names foo and bar into dependent names. There are three ways to do this:

  • Qualify them with this, as you have done. This has the downside that you need to do it everywhere you use the names. this is implicitly a dependent name.
  • Qualify them with the base class name, as X<T>::foo and X<T>::bar. This also needs to be done everywhere you use them, and additionally breaks the virtual dispatch mechanism if they turn out to be virtual methods.
  • Bring the dependent names into the non-dependent namespace by using X<T>::foo; and using X<T>::bar;.

Or, you can compile with VC++ which couldn't care less about the distinction between dependent and non-dependent names.

Tom
  • 7,269
  • 1
  • 42
  • 69
  • @Drax My life is currently hell because of this. I'm porting a large code base from VC++ to GCC. The rest of the team is still developing in VC++. It doesn't matter how often you explain the dependent/non-dependent distinction to them, they keep on breaking it and can't see what's wrong. "But it compiles fine for me..." – Tom Aug 20 '14 at 23:53
  • Is the thing about VC++ still true today? Because it doesn't seem to work. Maybe there's some option for it? – SWdV Apr 12 '19 at 22:23
  • @SWdV - very late comment, but I believe the VC++ compiler manages to get this right these days. Back when this was written, it was dire; not only did it not care about this distinction, it also didn't bother parsing template bodies until they were used, meaning you put put very nearly anything in the body of a template, so long as it was not used; the bug wouldn't become apparent until someone else used it and suddenly years-old template code won't compile. – Tom Jun 01 '23 at 11:59