0

I followed instructions I found on stackoverflow to implement linked list template class, I did it as follows:

template<typename T> class List;
template<typename T> std::ostream& operator<<(std::ostream&, const List<T>&);

template<typename T>
class List {
private:
    struct Item {
        T value;
        Item *next;
        Item *prev;

        Item(const T &value, Item *next, Item *prev)
                : value(value), next(next), prev(prev) {
        }
    };

    Item *head;
    Item *tail;
    int size;
public:
    List();    
    ~List();    
    List(const List&) = delete;    
    List& operator=(const List &) = delete;    
    friend std::ostream& operator<< <>(std::ostream&, const List<T>&);
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const List<T>& list) {
    Item* p = list.head;
    while (p != NULL) {
        os << p->value << " ";
        p = p->next;
    }
    return os;
}

however I get an error

error: 'Item' was not declared in this scope

I have no idea how as it's friended so I should have access to all private members right?

1 Answers1

4

Item being a member of every class template specialization of List cannot be found inside the global function (template) operator<<. You'll need typename List<T>::Item to look up the name Item within the class List<T>.

template <typename T>
std::ostream& operator<<(std::ostream& os, const List<T>& list) {
    typename List<T>::Item* p = list.head; // <- here
    while (p != NULL) {
        os << p->value << " ";
        p = p->next;
    }
    return os;
}
dyp
  • 38,334
  • 13
  • 112
  • 177
  • I am not sure if that's what you meant but I added it to the implementation like this List::Item* p = list.head; which gives error "'p' was not declared in this scope" – user3758262 Dec 20 '14 at 19:28
  • Hm. I don't fully understand what you did. See the recently added code block in my answer and this live example: http://coliru.stacked-crooked.com/a/f4722d370aaefa97 (I have added dummy implementations for the constructor and destructor) – dyp Dec 20 '14 at 19:30
  • well thank you, that worked, however I have no idea how and why, I've never seen typename keyword in this kind of context – user3758262 Dec 20 '14 at 19:33
  • See [Where and why do I have to put the “template” and “typename” keywords?](http://stackoverflow.com/q/610245). Essentially, you need to tell the compiler to search the name `Item` within the class `List` - therefore `List::Item` - and you need to tell it that it's a type (not e.g. a variable) by using `typename`. – dyp Dec 20 '14 at 19:34