1
template<typename T> class A {
protected:
    int member;
};

template<typename T> class B : public A<T> {
    B() {
        member = 12;
    }
};

When I try to compile the above program, I get:

test.cpp: In constructor ‘B<T>::B()’:
test.cpp:8:9: error: ‘member’ was not declared in this scope
         member = 12;
         ^~~~~~

I know how to solve the problem. I just change member=12 to this->member=12. My question is: why does the compiler not compile this?

I'll point out that the error is issued despite the fact that the template have not been instantiated in any way. It's just two classes defined, still in template form.

Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
  • 1
    not sure if this explains the "why" enough https://stackoverflow.com/questions/1120833/derived-template-class-access-to-base-class-member-data see the second top answer – 463035818_is_not_an_ai Jul 25 '19 at 07:34

1 Answers1

2

If you use a name in a way that doesn't reference the template parameter visually, it should absolutely not depend on the template parameter!

void foo();

template <typename T>
struct A : T {
    void bar() {
        foo();
    }
};

It could be very bad that if T has a foo member function then the call resolves to the member and not to the global function.

If there is no global foo you could argue that it could resolve to a member function/data member as fallback, but that would complicate the language and could be confusing to get right ("I want to call member foobar but I didn't realize that there was a global function that happens to have the right signature").

In your example someone could specialize A with no member data member. Would a hypothetical global member variable be used instead? With this-> it's unambiguous.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162