It's a rather simple project which I created with sole purpose of learning how to create a Makefile. I have searched this to a reasonable extent before posting here, but could not find a solution. If I include the *.cpp files in main.cpp the program compiles fine, with no undefined references (although it still has some bugs when running, which I plan to deal with later).
main.cpp:
#include <iostream>
#include "dupqueue.h"
using std::string;
using std::cout;
using std::cin;
using std::endl;
int main()
{
    DuplicateQueue<string> dqueue;
    for(int i = 0; i < 10; i++)
    {
         string name;
         cout << "Enter a name: ";
         cin >> name;
         dqueue.enqueue(name);
         cout << endl;
    }
    dqueue.duplicate();
    cout << "Double order:\n";
    while(!dqueue.is_empty()) cout << dqueue.dequeue() << endl;
    return 0;
}
dupqueue.h:
#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED
template <class T>
class Queue
{
public:
    Queue() : front(nullptr), rear(nullptr) {}
    ~Queue();
    Queue(const Queue& q); // explicitly disallowed
    Queue& operator=(const Queue& q); // explicitly disallowed
    void enqueue(const T& item);
    const T dequeue();
    bool is_empty() const
    {
        return front == nullptr;
    }
protected:
    struct Node
    {
        T item;
        Node * next;
        Node(const T& i) : item(i), next(nullptr) {}
    };
    Node * front;
    Node * rear;
};
template <class T>
class DuplicateQueue : public Queue<T>
{
public:
    void duplicate();
};
#endif //QUEUE_H_INCLUDED
queue.cpp:
#include "dupqueue.h"
template <class T>
Queue<T>::~Queue()
{
    Node * temp = front;
    while(!temp)
    {
        front = front->next;
        delete temp;
        temp = front;
    }
}
template <class T>
void Queue<T>::enqueue(const T& item)
{
    rear->next = new Node(item);
    rear = rear->next;
}
template <class T>
const T Queue<T>::dequeue()
{
    const T item = front->item;
    Node * temp = front;
    front = front->next;
    delete temp;
    return item;
}
dupqueue.cpp:
#include "dupqueue.h"
template <class T>
void DuplicateQueue<T>::duplicate()
{
    typename Queue<T>::Node * original_rear = Queue<T>::rear;
    typename Queue<T>::Node * temp = Queue<T>::front;
    while(temp != original_rear->next)
    {
        Queue<T>::rear->next = new typename Queue<T>::Node(temp->item);
        Queue<T>::rear = Queue<T>::rear->next;
        temp = temp->next;
    }
}
Makefile:
main: main.o queue.o dupqueue.o
    g++ -o main main.o queue.o dupqueue.o
main.o: main.cpp dupqueue.h queue.cpp dupqueue.cpp
    g++ -c main.cpp
queue.o: queue.cpp dupqueue.h
    g++ -c queue.cpp
dupqueue.o: dupqueue.cpp dupqueue.h
    g++ -c dupqueue.cpp
clean:
    rm -f main *.o
make output:
g++ -o main main.o queue.o dupqueue.o
main.o: In function `main':
main.cpp:(.text+0x83): undefined reference to `Queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::enqueue(
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0xb7): undefined reference to `DuplicateQueue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >:
:duplicate()'
main.cpp:(.text+0xf0): undefined reference to `Queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::dequeue(
)'
main.o: In function `DuplicateQueue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~DuplicateQueue()':
main.cpp:(.text._ZN14DuplicateQueueINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev[_ZN14DuplicateQueueINSt7__cxx1112basic_stringIcSt1
1char_traitsIcESaIcEEEED5Ev]+0x25): undefined reference to `Queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> 
> >::~Queue()'
collect2: error: ld returned 1 exit status
make: *** [Makefile:2: main] Error 1
