#include <iostream>
using namespace std;
template<typename T>
void println(T data) {
cout << data << endl;
}
template<typename T>
class List {
public:
class Item {
protected:
T data;
Item* prev;
Item* next;
public:
Item(T data, Item* prev, Item* next) {
this->data = data;
this->prev = prev;
this->next = next;
}
T* getData() {
return &data;
}
Item* getNext() {
return next;
}
Item* getPrev() {
return prev;
}
T const* getData() const {
return &data;
}
Item const* getNext() const {
return next;
}
Item const* getPrev() const {
return prev;
}
};
private:
class ExtendedItem : Item {
public:
void setPrev(Item* prev) {
this->prev = prev;
}
void setNext(Item* next) {
this->next = next;
}
void removeSelf() {
if (next)
((ExtendedItem*)next)->setPrev(prev);
if (prev)
((ExtendedItem*)prev)->setNext(next);
}
};
Item* first;
Item* last;
public:
List() {
println("Default constructor called");
first = NULL;
last = NULL;
}
List(List<T> const& other) {
println("Copy constructor called");
first = NULL;
last = NULL;
for (Item const* cur = other.getFront(); cur != NULL; cur = cur->getNext()) {
pushBack(*cur->getData());
}
}
List(List<T> &&) = delete;
~List() {
println("Destructor called");
while (first != NULL) {
Item* next = first->getNext();
// ((ExtendedItem*)first)->removeSelf();
delete first;
first = next;
}
}
Item* pushFront(T data) {
Item* newOne = new Item(data, NULL, first);
if (first != NULL)
((ExtendedItem*)first)->setPrev(newOne);
first = newOne;
if (last == NULL)
last = newOne;
return newOne;
}
Item* pushBack(T data) {
Item* newOne = new Item(data, last, NULL);
if (last != NULL)
((ExtendedItem*)last)->setNext(newOne);
last = newOne;
if (first == NULL)
first = newOne;
return newOne;
}
Item* getFront() {
return first;
}
Item* getBack() {
return last;
}
Item const* getFront() const {
return first;
}
Item const* getBack() const {
return last;
}
void remove(Item* element) {
if (element == NULL)
return;
((ExtendedItem*)element)->removeSelf();
if (element == first)
first = first->getNext();
if (element == last)
last = last->getPrev();
delete element;
}
template <typename C, bool Pred(T*, C)>
Item* find(C context) {
for (Item* cur = first; cur != NULL; cur = cur->getNext())
if (Pred(cur->getData(), context))
return cur;
return NULL;
}
};
List<size_t> newList(size_t a) {
List<size_t> result;
result.pushBack(a);
return result;
}
int main() {
List<size_t> a(newList(1));
for (List<size_t>::Item const* cur = a.getFront(); cur != NULL; cur = cur->getNext())
println(*cur->getData());
return 0;
}