3

The following code doesn't compile with gcc, but it compiles with clang.

struct Base {
  void base() {}
};

template< typename T >
struct Foo : Base {

  struct Bar : Base {
  };

  struct Baz : Bar {
    void f() {
      base();
    }
  };
};

int main() {
  Foo<int>::Baz{}.f();
}

gcc spits the following error:

13:11: error: cannot call member function 'void Base::base()' without object
   13 |       base();
      |       ~~~~^~

Interestingly, if I change it to this->base(); or Base::base();, then it compiles.

Why can't gcc find the Base class object? Baz is clearly a subclass of Base.

panshiyan
  • 39
  • 2

1 Answers1

3

I suppose, it's the same issue as in this question:

GCC issue: using a member of a base class that depends on a template argument

Inside of a template, the compiler does not examine a base class template, and therefore does not find the base() method, without adding this-> or Base::.

srim
  • 31
  • 3
  • 1
    "Inside of a template, the compiler does not examine the base class": This is not quite right. The base class must be a template, too, in order to run into the problem. Try to derive `Baz` from `Base` directly and it works. The key in the example is that the intermediate class `Bar` depends on a template parameter, and `Baz` derives from that templated class. I guess it plays no role that both are defined as nested classes. So yes, I think you need to use `this->base()` as explained in the linked post, and that gcc (and also MSVC) are right to reject the code while clang has a bug. – Sedenion Apr 12 '22 at 18:59
  • @Sedenion: Thanks, you are right! I was thinking of 'Bar' from the example when I wrote this (where it being a template is not directly visible), but yes, in general it does need to be a template! I've corrected my answer! – srim Apr 13 '22 at 09:20