I'm working on an assignment to make a linked list of Card objects, and I'm running into a linker error when compiling. In the Deck class cpp, I get an udefined reference to the overloaded << operator and to the LinkedList constructor for Card. I've tried compiling in both Dev C++ and g++
In dev I get the following error:
C:\Users\Chris\Dropbox\mohroo-2a\Deck.o Deck.cpp:(.text+0x1c): undefined reference to `operator<<(std::ostream&, LinkedList<Card> const&)'
C:\Users\Chris\Dropbox\mohroo-2a\Deck.o Deck.cpp:(.text+0x3e): undefined reference to `LinkedList<Card>::LinkedList()'
c:\program files (x86)\dev-cpp\mingw64\x86_64-w64-mingw32\bin\ld.exe            C:/Users/Chris/Dropbox/mohroo-2a/Deck.o: bad reloc address 0x0 in section `.pdata'
c:\program files (x86)\dev-cpp\mingw64\x86_64-w64-mingw32\bin\ld.exe    final link failed: Invalid operation
F:\Documents\collect2.exe   [Error] ld returned 1 exit status
in g++:
In file included from Deck.h:4:0,
             from Deck.cpp:1:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
In file included from LinkedList.cpp:1:0:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
In file included from Deck.h:4:0,
             from program.cpp:2:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x1c): undefined reference to `operator<<(std::ostream&, LinkedList<Card> const&)'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x1c): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `operator<<(std::ostream&, LinkedList<Card> const&)'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x3e): undefined reference to `LinkedList<Card>::LinkedList()'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x3e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LinkedList<Card>::LinkedList()'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.1/../../../../x86_64-pc-cygwin/bin/ld:     /tmp/cc3tT0cD.o: bad reloc address 0x0 in section `.pdata'
collect2: error: ld returned 1 exit status
Here is the code:
Deck.h
#ifndef DECK_H
#define DECK_H
#include <ostream>
#include "LinkedList.h"
#include "Card.h"
class Deck
{
    friend std::ostream &operator<<(std::ostream &ostr, const Deck &d);
    public:
        Deck();
    private:
        LinkedList<Card> theDeck;
        Node<Card> *top;
};
#endif
Deck.cpp
#include "Deck.h"
std::ostream &operator<<(std::ostream &ostr, const Deck &d)
{
    ostr << d.theDeck;
    return ostr;
}
Deck::Deck()
{
}
LinkedList.h
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <ostream>
#include "Node.h"
template <typename T>
class LinkedList
{
    template <typename K>
    friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l);
    public:
        LinkedList();
        ~LinkedList();
        void addNode(Node<T> *newNode);
        Node<T> *head;
};
template <typename T>
LinkedList<T>::LinkedList()
{
    head = 0;
}
template <typename T>
LinkedList<T>::~LinkedList()
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        Node<T> *temp = ptr->next;
        delete ptr;
        ptr = temp;
    }
}
template <typename T>
void LinkedList<T>::addNode( Node<T> *newNode)
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        ptr = ptr->next;
    }
    ptr->next = newNode;
}
template <typename K>
friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l)
{
    ostr << "[ ";
    Node<T> *ptr = l.head;
    while(ptr != 0)
    {
        ostr << ptr->data << " ";
        ptr = ptr->next;
    }
    ostr << "]";
    return ostr;
}
#endif
Node.h
#ifndef NODE_H
#define NODE_H
template <typename T>
class Node
{
    public:
        Node();
        Node(const T &nodeData);
        Node(const Node<T> *nextNode);
        Node(const T &nodeData, const Node *nextNode);
        T data;
        Node *next;
};
template <typename T>
Node<T>::Node()
    :data()
{
    next = 0;
}
template <typename T>
Node<T>::Node(const T &nodeData)
{
    data = nodeData;
    next = 0;
}
template <typename T>
Node<T>::Node(const Node<T> *nextNode)
    :data()
{
    next = nextNode;
}
template <typename T>
Node<T>::Node(const T &nodeData, const Node *nextNode)
{
    data = nodeData;
    next = nextNode;
}
#endif
Card.h
#ifndef CARD_H
#define CARD_H
#include <ostream>
class Card
{
      friend std::ostream &operator << (std::ostream &ostr, const Card &c);
      private:
            int value; //Ranges from 2-14, where Ace = 14, Jack = 11, Queen = 12, King = 13
            int suit; //Ranges from 1-4, where 1 = Clubs, 2 = Diamonds, 3 = Hearts, 4 = Spades
      public:
             Card();
             Card(int, int);
             Card operator=(const Card &crd);
             Card (const Card &obj);
             void setValue(int);
             void setSuit(int);
             int getValue();
             int getSuit();
};
#endif
Card.cpp
#include "Card.h"
std::ostream &operator<<(std::ostream &ostr, const Card &c)
{
    switch(c.value)
    {
    case 2:
        ostr << "Two";
        break;
    case 3:
        ostr << "Three";
        break;
    case 4:
        ostr << "Four";
        break;
    case 5:
        ostr << "Five";
        break;
    case 6:
        ostr << "Six";
        break;
    case 7:
        ostr << "Seven";
        break;
    case 8:
        ostr << "Eight";
        break;
    case 9:
        ostr << "Nine";
        break;
    case 10:
        ostr << "Ten";
        break;
    case 11:
        ostr << "Jack";
        break;
    case 12:
        ostr << "Queen";
        break;
    case 13:
        ostr << "King";
        break;
    case 14:
        ostr << "Ace";
        break;
    }
    ostr << " of ";
    switch(c.suit)
    {
    case 1:
        ostr << "Clubs";
        break;
    case 2:
        ostr << "Diamonds";
        break;
    case 3:
        ostr << "Hearts";
        break;
    case 4:
        ostr << "Spades";
        break;
    }
    return ostr;
}
Card::Card()
{
            value = 0;
            suit = 0;
};
Card::Card(const Card &obj)
{
                 value = obj.value;
                 suit = obj.suit;
};
Card Card::operator=(const Card &crd)
{
     suit = crd.suit;
     value = crd.value;
     return *this;
};
Card::Card(int tvalue, int tsuit)
{
               value = tvalue;
               suit = tsuit;
};
void Card::setValue(int tempValue)
{
     value = tempValue;
}
void Card::setSuit(int tempSuit)
{
     suit = tempSuit;
}
int Card::getValue()
{
    return value;
}
int Card::getSuit()
{
    return suit;
}
and lastly program.cpp
#include <iostream>
#include "Deck.h"
using namespace std;
int main()
{
    Card someCard(2,4);
    Card otherCard(14,1);
    cout << someCard << "\n" << otherCard << endl;
}
So any ideas? I've tried looking this up and it seems like a linker error but when I compile using g++ *.cpp -o main it produces the above error. I've hit a wall with what to do next. Thanks in advance
EDIT:
LinkedList.h now looks like this
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <ostream>
#include "Node.h"
template <typename T>
class LinkedList
{
    template <typename K>
    friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l);
    public:
        LinkedList();
        ~LinkedList();
        void addNode(Node<T> *newNode);
        Node<T> *head;
};
template <typename T>
LinkedList<T>::LinkedList()
{
    head = 0;
}
template <typename T>
LinkedList<T>::~LinkedList()
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        Node<T> *temp = ptr->next;
        delete ptr;
        ptr = temp;
    }
}
template <typename T>
void LinkedList<T>::addNode( Node<T> *newNode)
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        ptr = ptr->next;
    }
    ptr->next = newNode;
}
template <typename K>
friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l)
{
    ostr << "[ ";
    Node<T> *ptr = l.head;
    while(ptr != 0)
    {
        ostr << ptr->data << " ";
        ptr = ptr->next;
    }
    ostr << "]";
    return ostr;
}
#endif
 
     
    