List.h
#pragma once
#ifndef GUARD_LIST_H
#define GUARD_LIST_H
#include "List.h"
#include <stdexcept>
#include <iostream>
template<typename T>
class List
{
struct Node
{
Node* prev;
T key;
Node* next;
Node(Node* p, T k, Node* n): prev{p}, key{k}, next{n} {}
};
public:
//default constructor creates a sentinal object
List() : sz{ 0 }, head{ new Node(nullptr, T(), nullptr) }, tail{ head } { }
explicit List(std::istream& is):sz{ 0 }, head{ new Node(nullptr, T(), nullptr) }, tail{ head } { read_in(is); }
~List();
//types
using iterator = Node*;
using const_iterator = const Node*;
using value_type = T;
using reference = T&;
using const_reference = const T&;
using size_type = size_t;
//functions
iterator begin() { return head; }
const_iterator begin() const { return head; }
iterator end() { return tail; }
const_iterator end() const { return tail; }
reference front() { return head->key; }
const_reference front() const { return head->key; }
reference back() { return tail->prev->key; }
const_reference back() const { return tail->prev->key; }
bool empty() const { return head == tail ; }
size_type size() const { return sz; }
iterator operator++() { return this->next; }
iterator operator--() { return this->prev; }
//std::ostream& operator<<(std::ostream& os) { os << }
//modifier function
void push_back(value_type);
void erase(iterator);
void pop_back();
void push_front(value_type);
void pop_front();
iterator search(const value_type key) const
{
iterator x = head;
while (x != end() && x->key != key)
{
x = x->next;
}
return x;
}
void insert(iterator pos, const value_type key)
{
if (empty())
{
iterator x = new Node(nullptr, key, tail);
head = x;
tail->prev = x;
}
else //if not empty
{
if (pos == head)
{
iterator x = new Node(nullptr, key, head);
head->prev = x;
head = x;
}
else
{
if (pos == tail)
{
iterator x = new Node(tail->prev, key, tail);
tail->prev->next = x;
tail->prev = x;
}
else
{
iterator x = new Node(pos, key, pos->next);
pos->next->prev = x;
pos->next = x;
}
}
}
++sz;
}
private:
std::istream& read_in(std::istream& is)
{
if (is)
{
for (value_type x; is >> x; )
push_back(x);
}
is.clear();
return is;
}
size_type sz;
iterator head;
iterator tail;
};
template<typename T>
List<T>::~List()
{
iterator tmp;
for (;head;head = tmp) {
tmp = head->next;
delete head;
}
}
template<typename T>
inline void List<T>::push_back(value_type key)
{
insert(tail, key);
}
template<typename T>
inline void List<T>::erase(iterator pos)
{
if (empty())
throw std::domain_error("list is empty.");
else
{
if (pos == head)
{
iterator x = head;
head = head->next;
head->prev = nullptr;
delete x;
}
else
{
iterator x = pos;
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
delete x;
}
--sz;
}
}
template<typename T>
inline void List<T>::pop_back()
{
erase(tail->prev);
}
template<typename T>
inline void List<T>::push_front(value_type key)
{
insert(head, key);
}
template<typename T>
inline void List<T>::pop_front()
{
erase(head);
}
#endif // !GUARD_LIST_H
The above code compiled and worked fine.
I was getting the following errors when I tried to separate interface and implementation into header and source files respectively.
Any sugguestions? I am just learning C++, data structures and algorithms. Thank you.