0

I'm trying to access a parent method from a derived template class, but despite using public access everywhere, and "this->" to be safe, I'm getting the error.

error: 'class Derived<TagTypeA, int>' has no member named 'insert'

I don't know if I'm making a stupid mistake somewhere, but I can't work out why the Derived class can't access the parent's stuff.

I have code that looks something like below, and also here: https://godbolt.org/z/nMbe4fMnM

#include <bits/stdc++.h>

struct TagTypeA;

template<typename T>
class Base {
  public:
    std::set<T> data;
    void insert(const T& v) { data.insert(v); }
    void erase(const T& v) { data.erase(v); }
};

template<typename Tag, typename T>
class Derived : public Base<T> {};

// specialization of Derived
template<typename T>
class Derived<TagTypeA, T> {
  public:
    void call_parent_insert(const T& v) { this->insert(v); }
};

int main() 
{ 
    Derived<TagTypeA, int> foo;
    foo.call_parent_insert(1);
}
Paradox
  • 1,935
  • 1
  • 18
  • 31
  • `Derived` has no base classes? – Alan Birtles Apr 26 '21 at 07:08
  • But it's a specialization of Derived which has Base as its base class – Paradox Apr 26 '21 at 07:09
  • 1
    Specialisations are basically separate classes and have no relation to the original class – Alan Birtles Apr 26 '21 at 07:10
  • 1
    Unrelated, but mandatory to read: [Why should I **not** `#include `?](https://stackoverflow.com/Questions/31816095/Why-Should-I-Not-Include-Bits-Stdc-H.) – Ted Lyngmo Apr 26 '21 at 07:11
  • Oh, I didn't know that. I thought because you can't have a specialized class without the unspecialized version that it would know about the inheritance somehow, but I guess not. Anyhow, writing `class Derived : public Base` fixed the issue. Thanks! – Paradox Apr 26 '21 at 07:14

1 Answers1

2

Compiler needs a suspect base class to contain method in question in order to consider the code legal.

The class described by template specialization

template<typename T>
class Derived<TagTypeA, T> {
  public:
    void call_parent_insert(const T& v) { this->insert(v); }
};

declares that type Derived<TagTypeA ,T> doesn't have base class. There is nowhere it can get insert method from. Declaration should be looking like this

template<typename T>
class Derived<TagTypeA, T> : public Base<T> {

It's not necessary that insert would be defined in Base<T> at moment of this declaration. It might be defined in a specialization of Base later. It matters only at point of instantiation of Derived as you cleverly used this->insert expression.

If an unspecialized Derived never will be used, it can be declared as incomplete class. Its only purpose in that case is to declare existence of template and this case reduce amount of cryptic template errors in case of misuse.

template<typename Tag, typename T> class Derived;
Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42