cpp
#pragma once
template<typename T>
class list
{
private:
struct _listnode
{
_listnode(const T& v)
: data(v), prev(nullptr), next(nullptr) {}
_listnode(T&& v)
: data(static_cast<T&&>(v)), prev(nullptr), next(nullptr) {}
_listnode* prev;
_listnode* next;
T data;
};
_listnode* _head;
_listnode* _tail;
size_t _size;
public:
class _iterator
{
private:
_listnode* node;
public:
_iterator(_listnode* n = nullptr) :node(n) {}
T& operator*() const {
return node->data;
}
_iterator& operator++() {
node = node->next;
return *this;
}
_iterator operator++(int) {
auto temp = *this;
node = node->next;
return temp;
}
_iterator& operator--(){
node = node->prev;
return *this;
}
_iterator operator--(int) {
auto temp = *this;
node = node->prev;
return temp;
}
bool operator==(const _iterator& other) const {
return node == other.node;
}
bool operator!=(const _iterator& other) const {
return node != other.node;
}
_listnode* getNode() const {
return node;
}
};
class _const_iterator
{
private:
const _listnode* node;
public:
_const_iterator(const _listnode* n = nullptr) :node(n) {}
const T& operator*() const {
return node->data;
}
_const_iterator& operator++() {
node = node->next;
return *this;
}
_const_iterator operator++(int) {
auto temp = *this;
node = node->next;
return temp;
}
_const_iterator& operator--() {
node = node->prev;
return *this;
}
_const_iterator operator--(int) {
auto temp = *this;
node = node->prev;
return temp;
}
bool operator==(const _const_iterator& other) const {
return node == other.node;
}
bool operator!=(const _const_iterator& other) const {
return node != other.node;
}
const _listnode* getNode() const {
return node;
}
};
list() : _head(nullptr), _tail(nullptr), _size(0) {}
list(const list& other) : _head(nullptr), _tail(nullptr), _size(0) {
for (auto it : other) { push_back(it); }
}
list(list&& other) : _head(other._head), _tail(other._tail), _size(other._size) {
other._head = nullptr;
other._tail = nullptr;
other._size = 0;
}
~list() {
clear();
}
list& operator=(const list& other) {
if (this != &other)
{
clear();
for (auto it : other) { push_back(it); }
}
return *this;
}
list& operator=(list&& other) {
if (this != &other)
{
clear();
_head = other._head;
_tail = other._tail;
_size = other._size;
other._head = nullptr;
other._tail = nullptr;
other._size = 0;
}
return *this;
}
void clear() {
while (_head)
{
auto temp = _head;
_head = _head->next;
delete temp;
}
_head = nullptr;
_tail = nullptr;
_size = 0;
}
void push_back(const T& value) {
auto newNode = new _listnode(value);
newNode->prev = _tail;
newNode->next = nullptr;
if (_tail)
_tail->next = newNode;
else
_head = newNode;
_tail = newNode;
_size++;
}
void push_back(T&& value) {
auto newNode = new _listnode(static_cast<T&&>(value));
newNode->prev = _tail;
newNode->next = nullptr;
if (_tail)
_tail->next = newNode;
else
_head = newNode;
_tail = newNode;
_size++;
}
void push_front(const T& value) {
auto newNode = new _listnode(value);
newNode->prev = nullptr;
newNode->next = _head;
if (_head)
_head->prev = newNode;
else
_tail = newNode;
_head = newNode;
_size++;
}
void push_front(T&& value) {
auto newNode = new _listnode(static_cast<T&&>(value));
newNode->prev = nullptr;
newNode->next = _head;
if (_head)
_head->prev = newNode;
else
_tail = newNode;
_head = newNode;
_size++;
}
void pop_back() {
if (_tail)
{
auto temp = _tail;
_tail = _tail->prev;
if (_tail)
_tail->next = nullptr;
else
_head = nullptr;
delete temp;
_size--;
}
}
void pop_front() {
if (_head)
{
auto temp = _head;
_head = _head->next;
if (_head)
_head->prev = nullptr;
else
_tail = nullptr;
delete temp;
_size--;
}
}
_iterator insert(_iterator pos, const T& value) {
auto posNode = pos.getNode();
if (!posNode)
{
push_back(value);
return _iterator(_tail);
}
auto newNode = new _listnode(value);
newNode->prev = posNode->prev;
newNode->next = posNode;
if (posNode->prev)
posNode->prev->next = newNode;
else
_head = newNode;
posNode->prev = newNode;
_size++;
return _iterator(newNode);
}
_iterator insert(_iterator pos, T&& value) {
auto posNode = pos.getNode();
if (!posNode)
{
push_back(static_cast<T&&>(value));
return _iterator(_tail);
}
auto newNode = new _listnode(static_cast<T&&>(value));
newNode->prev = posNode->prev;
newNode->next = posNode;
if (posNode->prev)
posNode->prev->next = newNode;
else
_head = newNode;
posNode->prev = newNode;
_size++;
return _iterator(newNode);
}
_iterator erase(_iterator pos) {
auto posNode = pos.getNode();
if (!posNode) return end();
if (posNode->prev)
posNode->prev->next = posNode->next;
else
_head = posNode->next;
if (posNode->next)
posNode->next->prev = posNode->prev;
else
_tail = posNode->prev;
auto nextNode = posNode->next;
delete posNode;
_size--;
return _iterator(nextNode);
}
size_t size() const {
return _size;
}
bool empty() const {
return _size == 0;
}
T& front() {
return _head->data;
}
const T& front() const {
return _head->data;
}
T& back() {
return _tail->data;
}
const T& back() const {
return _tail->data;
}
_iterator begin() {
return _iterator(_head);
}
_const_iterator begin() const {
return _const_iterator(_head);
}
_iterator end() {
return _iterator(nullptr);
}
_const_iterator end() const {
return _const_iterator(nullptr);
}
};