#include <stdexcept>               //   defines std::runtime_error

/* Standard constructor creates an empty deque. */
template <typename Object>
AltLinkedDeque<Object>::AltLinkedDeque() : head(NULL), tail(NULL), n(0) { }

/* Return the number of objects in the deque. */ 
template <typename Object>
int AltLinkedDeque<Object>::size() const {
    return n;
}

/* Determine if the deque is currently empty. */
template <typename Object>
bool AltLinkedDeque<Object>::empty() const {
    return n == 0;
}

/* Return a const reference to the front object in the deque. */
template <typename Object>
const Object& AltLinkedDeque<Object>::front() const {
    if (empty()) throw std::runtime_error("Access to empty deque");
    return head->elem;
}

/* Return a const reference to the back object in the deque. */
template <typename Object>
const Object& AltLinkedDeque<Object>::back() const {
    if (empty()) throw std::runtime_error("Access to empty deque");
    return tail->elem;
}

/* Insert an object at the front of the deque. */
template <typename Object>
void AltLinkedDeque<Object>::push_front(const Object& e) {

    // YOUR CODE HERE

}

/* Remove the back object from the deque. */
template <typename Object>
void AltLinkedDeque<Object>::pop_back()  {

    // YOUR CODE HERE

}

/* Insert an object at the back of the deque. */
template <typename Object>
void AltLinkedDeque<Object>::push_back(const Object& e) {

    // would be symmetric to push_front
}

/* Remove the front object from the deque. */
template <typename Object>
void AltLinkedDeque<Object>::pop_front()  {

    // would be symmetric to pop_back

}

// housekeeping functions remain

template <typename Object>
void AltLinkedDeque<Object>::removeAll() {   // remove entire deque contents
    while (!empty()) pop_back();             // for simplicity, reuse existing method
}

template <typename Object>
void AltLinkedDeque<Object>::copyFrom(const AltLinkedDeque& other) {
    Node* walk(other.head);                      // the front node
    while (walk != NULL) {
        push_back(walk->elem);
        walk = walk->next;
    }
}

/* Copy constructor */
template <typename Object>
AltLinkedDeque<Object>::AltLinkedDeque(const AltLinkedDeque& other)
    : head(NULL), tail(NULL), n(0)
{
    copyFrom(other);
}

/* Destructor */
template <typename Object>
AltLinkedDeque<Object>::~AltLinkedDeque() {
    removeAll();
}

/* Assignment operator */
template <typename Object>
AltLinkedDeque<Object>&
AltLinkedDeque<Object>::operator=(const AltLinkedDeque& other) {
    if (this != &other) {                           // avoid self copy (x = x)
        removeAll();                                // remove old contents
        copyFrom(other);                            // copy new contents
    }
    return *this;
}
