3

One of the template classes exercises in my C++ class asks to make those two classes work:

file node.h

#ifndef node_h
#define node_h


template<typename T>
class Node
{
private:
    friend class Stack;
    Node(T value, Node *next);
    T value;
    Node *next;
};

#endif /* node_h */

and file stack.h

#ifndef stack_h
#define stack_h

#include "node.h"

template<typename T>
class Stack  // ERROR HERE!
{
public:
    Stack() : top(0) {}
    void push(T value);
    T pop();
private:
    Node<T> *top;
};

template<typename T>
void Stack<T>::push(T value)
{
    top = new Node<T>(value, top);
}

template<typename T>
T Stack<T>::pop()
{
    T result = top->value;
    top = top->next;
    return result;
}

#endif /* stack_h */

I'm getting a "Redefinition of 'Stack' as different kind of symbol" thrown by the compiler. I know it has to do with the declaration of Stack as a friend class in the node.h file, but if I remove that line, then Stack does not get access to the node's private members. Why is this issue occurring?

Petio Petrov
  • 123
  • 1
  • 9

1 Answers1

3

Instead of

friend class Stack;

You need

friend class Stack<T>;

In order to actually get this to compile though, I had to also add a forward reference to Stack above Node. I didn't think this was necessary, so maybe someone can explain why a forward reference is needed here. Alternatively, this link suggests template<typename U> friend class Stack; works without a forward reference, but this makes Stack<char> a friend of Node<int> which I don't think is the OPs intent. Maybe someone could clarify. Complies with g++ 7.2.0

template<typename T> class Stack;

template<typename T>
class Node
{
private:
    friend class Stack<T>;
    Node(T value, Node *next);
    T value;
    Node *next;
};
MFisherKDX
  • 2,840
  • 3
  • 14
  • 25
  • This may help: https://stackoverflow.com/questions/4492062/why-does-a-c-friend-class-need-a-forward-declaration-only-in-other-namespaces – Mark Mucha Oct 28 '17 at 00:07
  • @MarkMucha I think this one is more clear in the OPs case. I'll edit my answer https://stackoverflow.com/questions/8967521/class-template-with-template-class-friend-whats-really-going-on-here – MFisherKDX Oct 28 '17 at 00:17
  • Now I have a second issue though where the push() method cannot find an appropriate Node constructor. Undefined symbols for architecture x86_64: "Node::Node(int, Node*)", referenced from: Stack::push(int) in main.o Should I be asking for help with that here or in a new question? – Petio Petrov Oct 28 '17 at 01:45
  • Yeah. Make sure you implement it. You only declared it in the code you pasted. Replace `Node(T value, Node *next);` with `Node(T v, Node *n) : value(v), next(n) {}` – MFisherKDX Oct 28 '17 at 01:56