-1

I'm making a Linked list which is generic in nature and have some basic functionality. Then I'm trying to make another template class called "Set" which is inheriting from LinkedList. But when I try to access "head" which is a Node<>* defined in Linked List. It's giving an error. My files are:

LinkedList.h

template <typename T>
struct Node {
        T data;
        Node<T> *next;
};

template <typename T>
class LinkedList {
public:
        Node<T>* head;
        int size;

        LinkedList();
        LinkedList(const LinkedList<T> &lst);
        ~LinkedList();

        Node<T>* getHead();
        Node<T>* getTail();
};

template <typename T>
class Set:public LinkedList<T> {
public:
        void insert(T item);
        friend ostream&(ostream& out, const Set<T> set)
};

and an implementation of insert is:

template <typename T>
void Set<T>::insert(T item) {
       Node<T>* temp = head;
       bool present = false;

       while (temp != NULL) {
                if (temp->data == item) {
                        present = true;
                }

                temp = temp->next;
       }

        if (present == false) {
                /*Node<T> *tail = getTail();
                Node<T>* newTail = new Node<T>(item);
                newTail->next = NULL;
                tail->next = newTail;*/
        }
}

It says:

error: "head" was not declared in this scope in line "Node<T>* temp = head"

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
muqsitnawaz
  • 236
  • 2
  • 9
  • We require you to tell us _what error_. – Lightness Races in Orbit Dec 06 '14 at 21:34
  • @0x499602D2 That's obviously not a duplicate. For one this OP doesn't even know that he needs to write `this->`, so how can he be asking _why_ he needs to write it? – Lightness Races in Orbit Dec 06 '14 at 21:42
  • @LightnessRacesinOrbit That's usually what we do when people have a, say, `template`/`typename` issue. Why does it not apply here? – David G Dec 06 '14 at 21:44
  • @0x499602D2: For a start, that one was deemed a C++ FAQ entry by "committee" decision; the "dupe" you identified was not. Furthermore, if we're just going to close every question we see as a duplicate of some general-reference question on the same topic but only loosely similar to the actual question asked, then what are we doing here, really? What's the point? Might as well just give people page numbers to C++ books and be done with it. – Lightness Races in Orbit Dec 06 '14 at 21:47
  • @LightnessRacesinOrbit Alrighty, reopened. – David G Dec 06 '14 at 21:47

2 Answers2

4

This C++ oddity is due to two-phase lookup and the fact that head is a dependant name (as a member of a base class that depends on the "current" class's template arguments):

[C++11: 14.6.2/3]: In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [..]

Bypass unqualified lookup by introducing this into the expression (per [C++11: 3.4.5]):

Node<T>* temp = this->head;
//              ^^^^^^

There's a longer explanation on this previous Stack Overflow answer:


Here's a minimal(ish) testcase:

#include <iostream>

template <typename T>
struct Base
{
    int x = 42;
};

template <typename T>
struct Derived : Base<T>
{
    void foo();
};

template <typename T>
void Derived<T>::foo()
{
    std::cout << x << '\n';
}

int main()
{
    Derived<void> d;
    d.foo();
}
// main.cpp: In member function 'void Derived<T>::foo()':
// main.cpp:18:18: error: 'x' was not declared in this scope
//      std::cout << x << '\n';
//                   ^

(live demo)

To fix, change foo thus:

template <typename T>
void Derived<T>::foo()
{
    std::cout << this->x << '\n';
}

(live demo)

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • But how to get head if i'm declaring a function as, "friend" such as: friend ostream& operator<<() { – muqsitnawaz Dec 06 '14 at 21:51
  • But how to get head if i'm declaring a function as, "friend" such as: friend ostream& operator<<(ostream& out, Set set) { Node* temp = this->head; } this would give me an error since a friend function doesn't refer to an object. – muqsitnawaz Dec 06 '14 at 21:51
  • @user3813179: Um, `set.head`??? BTW please for the love of Jibbers Crabst take that `Set` in by const reference? – Lightness Races in Orbit Dec 06 '14 at 21:53
  • That has helped. But how to make it a template? I'm doing some edits in my question. Kindly have a look. – muqsitnawaz Dec 06 '14 at 21:56
  • Please have another look in the question at the last lines. – muqsitnawaz Dec 06 '14 at 21:59
  • @user3813179: I reverted your edit. You added a completely unrelated question. If you have a fresh question please work on it for a while yourself then if you're still stuck post it separately. – Lightness Races in Orbit Dec 06 '14 at 22:10
2

You're inheriting from a dependent base class so member access needs to be qualified with this:

Node<T>* temp = this->head;

For more information, see this thread.

Community
  • 1
  • 1
David G
  • 94,763
  • 41
  • 167
  • 253
  • For an upvote provide standardese or a reference of some kind. I can never remember where I put it. – Lightness Races in Orbit Dec 06 '14 at 21:34
  • I've tried doing this, but still it says, "head was not declared in this scope". – muqsitnawaz Dec 06 '14 at 21:36
  • @user3813179 That's not the error you would get if you did `this->head`. Are you using an unqualified `head` elsewhere? – David G Dec 06 '14 at 21:38
  • @LightnessRacesinOrbit [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) – David G Dec 06 '14 at 21:39
  • @0x499602D2: Not in a comment, bub. I'm suggesting an improvement to your _answer_. – Lightness Races in Orbit Dec 06 '14 at 21:41
  • But how to get head if i'm declaring a function as, "friend" such as: friend ostream& operator<<(ostream& out, Set set) { Node* temp = this->head; } this would give me an error since a friend function doesn't refer to an object. – muqsitnawaz Dec 06 '14 at 21:53
  • @user3813179 That would be `set.head`. – David G Dec 06 '14 at 21:58