3

If I work with classes, everything is just fine:

struct Base1 {
  int value;
  Base1(int value) : value(value) { }
};

struct Test1 : public Base1 {
  int getValue() { return value; }  
  Test1(int value) : Base1(value) { }
};

but with templates scope resolution is needed:

template <typename T>
struct Base {
  T value;
  Base(T value) : value(value) { }
};

template <typename T>
struct Test : public Base<T> {
  typedef Base<T> parent;
  T getValue() { return parent::value; }  // why do I need to use parent:: here?
  Test(T value) : parent(value) { }
};

Without the scope resolution I receive error 'value' was not declared in this scope (gcc compiler used). Why?

Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
  • What if you defined Test as follows: `struct Test : Public Base` ? – Brady May 23 '12 at 15:02
  • @Brady: then I receive an error `'Test' is not a template` - template must be created before it is specialized. – Jan Turoň May 23 '12 at 15:06
  • @Brady: The compiler would give you an error. The correct C++ syntax is the one used by OP. – Gorpik May 23 '12 at 15:06
  • For detailed explanation I like [this answer](http://stackoverflow.com/a/7908530/546632) – Fiktik May 23 '12 at 15:17
  • possible duplicate of [Inheritance and templates in C++ - why are methods invisible?](http://stackoverflow.com/questions/1567730/inheritance-and-templates-in-c-why-are-methods-invisible) – Bo Persson May 23 '12 at 15:20

2 Answers2

6

Because the compiler is not aware that value is dependent on the template argument. As such, it attempts to resolve it during the first pass (prior to instantiating the template), and fails.

The two options are to use the scoping resolution, as you have, or use this->value. Since this is always a dependent name, this will force the evaluation to occur during the second pass.

See http://ideone.com/07odY

Edit: And as to the why it needs to be done at all:

While Test<T> derives from Base<T>, due to template specialization you could make Base<std::string> (for example) be totally different than the normal Base<T>, and not have a member named value, or it could be of a different type, or anything. By forcing it to be a dependent name, the compiler is forced to wait until it knows the actual type involved before checking.

Dave S
  • 20,507
  • 3
  • 48
  • 68
3

Because there is no other way to tell the compiler (since it is not defined within Tests body) that value is a dependent name. You are forcing the compiler to say that "Okay! Believe me when I say that there is such a member value for the type T."

dirkgently
  • 108,024
  • 16
  • 131
  • 187