|
@@ -12,18 +12,21 @@
|
|
|
#include <list>
|
|
|
#include <memory>
|
|
|
#include <utility>
|
|
|
+#include <iostream>
|
|
|
+#include <stdexcept>
|
|
|
|
|
|
template<typename T>
|
|
|
struct XorListNode {
|
|
|
public:
|
|
|
XorListNode() = delete;
|
|
|
|
|
|
- XorListNode(const T &val) {
|
|
|
+ explicit XorListNode(const T &val) {
|
|
|
val_ = val;
|
|
|
}
|
|
|
|
|
|
- XorListNode(const T &&val) {
|
|
|
- val_ = std::forward<XorListNode<T> >(val);
|
|
|
+ explicit XorListNode(T &&val) {
|
|
|
+ val_ = std::move(val);//std::forward<T>(val);
|
|
|
+ //std::cout << "move-constructor\n";
|
|
|
}
|
|
|
|
|
|
XorListNode *right(const XorListNode *left) const {
|
|
@@ -59,7 +62,6 @@ struct FwdXorListIterator {
|
|
|
|
|
|
FwdXorListIterator(Node *x, Node *prev) : node_(x), left_(prev) {}
|
|
|
|
|
|
- // Must downcast from _List_node_base to _List_node to get to value.
|
|
|
reference operator*() const {
|
|
|
return node_->val_;
|
|
|
}
|
|
@@ -115,16 +117,21 @@ template<typename T, typename Allocator = std::allocator<T> >
|
|
|
class XorList {
|
|
|
|
|
|
private:
|
|
|
- typedef typename Allocator::template rebind<XorListNode<T>>::other allocator_type;
|
|
|
- typedef __gnu_cxx::__alloc_traits<allocator_type> Allocator_traits;
|
|
|
+
|
|
|
+ typedef typename __gnu_cxx::__alloc_traits<Allocator>::template
|
|
|
+ rebind<T>::other T_alloc_type;
|
|
|
+ typedef __gnu_cxx::__alloc_traits<T_alloc_type> T_alloc_traits;
|
|
|
+
|
|
|
+ typedef typename T_alloc_traits::template rebind<XorListNode<T> >::other Node_alloc_type;
|
|
|
+ typedef __gnu_cxx::__alloc_traits<Node_alloc_type> Node_alloc_traits;
|
|
|
|
|
|
public:
|
|
|
// types:
|
|
|
typedef T value_type;
|
|
|
- typedef typename Allocator_traits::pointer pointer;
|
|
|
- typedef typename Allocator_traits::const_pointer const_pointer;
|
|
|
- typedef value_type& reference;
|
|
|
- typedef const value_type& const_reference;
|
|
|
+ typedef typename T_alloc_traits::pointer pointer;
|
|
|
+ typedef typename T_alloc_traits::const_pointer const_pointer;
|
|
|
+ typedef value_type &reference;
|
|
|
+ typedef const value_type &const_reference;
|
|
|
|
|
|
typedef FwdXorListIterator<T> iterator;
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
@@ -133,249 +140,222 @@ public:
|
|
|
//typedef Allocator allocator_type;
|
|
|
|
|
|
explicit XorList(const Allocator &alloc = Allocator())
|
|
|
- : front_(nullptr), back_(nullptr), size_(0), allocator_(allocator_type()) {}
|
|
|
+ : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) {}
|
|
|
|
|
|
- XorList(size_type count, const_reference value = T(), const Allocator &alloc = Allocator())
|
|
|
- : front_(nullptr), back_(nullptr), size_(0), allocator_(allocator_type()) {
|
|
|
+ explicit XorList(size_type count, const_reference value = T(), const Allocator &alloc = Allocator())
|
|
|
+ : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) {
|
|
|
for (size_type i = 0; i < count; i++)
|
|
|
push_back(value);
|
|
|
}
|
|
|
|
|
|
- XorList(const XorList &other) {
|
|
|
- *this = other;
|
|
|
- }
|
|
|
+ XorList &operator=(const XorList &other) {
|
|
|
+ if (this == &other)
|
|
|
+ return *this;
|
|
|
|
|
|
- XorList(const XorList &&other) noexcept {
|
|
|
- *this = other;
|
|
|
- }
|
|
|
+ clear();
|
|
|
|
|
|
- ~XorList() {
|
|
|
- XorListNode<T> *xleft = nullptr;
|
|
|
- XorListNode<T> *x = front_;
|
|
|
- while (x != back_) {
|
|
|
- XorListNode<T> *xnext = x->right(xleft);
|
|
|
- if (xnext) {
|
|
|
- allocator_.destroy(xleft);
|
|
|
- allocator_.deallocate(xleft, 1);
|
|
|
- }
|
|
|
- xleft = x;
|
|
|
- x = xnext;
|
|
|
- }
|
|
|
+ allocator_ = Node_alloc_type(other.allocator_);
|
|
|
+ front_ = back_ = nullptr;
|
|
|
+ size_ = 0;
|
|
|
|
|
|
- if (xleft) {
|
|
|
- allocator_.destroy(xleft);
|
|
|
- allocator_.deallocate(xleft, 1);
|
|
|
- }
|
|
|
- if (x) {
|
|
|
- allocator_.destroy(x);
|
|
|
- allocator_.deallocate(x, 1);
|
|
|
- }
|
|
|
+ for (const auto& i: other)
|
|
|
+ push_back(i);
|
|
|
+ std::cout << "Copy assignment\n";
|
|
|
+ return *this;
|
|
|
}
|
|
|
|
|
|
- XorList &operator=(const XorList &other) {
|
|
|
+ XorList &operator=(XorList &&other) noexcept {
|
|
|
if (this == &other)
|
|
|
return *this;
|
|
|
|
|
|
- this->~XorList();
|
|
|
+ clear();
|
|
|
+
|
|
|
this->front_ = other.front_;
|
|
|
this->back_ = other.back_;
|
|
|
this->size_ = other.size_;
|
|
|
- this->allocator_ = other.allocator_;
|
|
|
+ this->allocator_ = std::move(other.allocator_);
|
|
|
+
|
|
|
+ other.front_ = other.back_ = nullptr;
|
|
|
+ other.size_ = 0;
|
|
|
+
|
|
|
+ std::cout << "Move assignment\n";
|
|
|
+ return *this;
|
|
|
}
|
|
|
|
|
|
- XorList &operator=(const XorList &&other) noexcept {
|
|
|
- if (this == &other)
|
|
|
- return *this;
|
|
|
+ ~XorList() {
|
|
|
+ clear();
|
|
|
+ }
|
|
|
|
|
|
- this->~XorList();
|
|
|
- this->front_ = other.front_;
|
|
|
- this->back_ = other.back_;
|
|
|
- this->size_ = other.size_;
|
|
|
- this->allocator_ = other.allocator_;
|
|
|
+ template <typename xorlist_t>
|
|
|
+ explicit XorList(xorlist_t &&other) noexcept : XorList() {
|
|
|
+ *this = std::forward<xorlist_t>(other);
|
|
|
}
|
|
|
|
|
|
- value_type front() {
|
|
|
+ value_type front() const {
|
|
|
return front_->val_;
|
|
|
}
|
|
|
|
|
|
- value_type back() {
|
|
|
+ value_type back() const {
|
|
|
return back_->val_;
|
|
|
}
|
|
|
|
|
|
- iterator begin() {
|
|
|
+ iterator begin() const {
|
|
|
return iterator(front_, nullptr);
|
|
|
}
|
|
|
|
|
|
- iterator end() {
|
|
|
+ iterator end() const {
|
|
|
if (!back_)
|
|
|
return iterator(nullptr, nullptr);
|
|
|
return ++iterator(back_, back_->left(nullptr));
|
|
|
}
|
|
|
|
|
|
- reverse_iterator rbegin() {
|
|
|
+ reverse_iterator rbegin() const {
|
|
|
return reverse_iterator(front_, nullptr);
|
|
|
}
|
|
|
|
|
|
- reverse_iterator rend() {
|
|
|
+ reverse_iterator rend() const {
|
|
|
return ++reverse_iterator(back_, back_->left(nullptr));
|
|
|
}
|
|
|
|
|
|
- size_type size() {
|
|
|
+ size_type size() const {
|
|
|
return size_;
|
|
|
}
|
|
|
|
|
|
- void push_back(const value_type &val) {
|
|
|
- XorListNode<T> *past_back = back_;
|
|
|
- back_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
- allocator_.construct(back_, std::forward<XorListNode<T> >(val));
|
|
|
- back_->assign_leftright(past_back, nullptr);
|
|
|
- if (past_back)
|
|
|
- past_back->assign_leftright(past_back->left(nullptr), back_);
|
|
|
- if (!front_)
|
|
|
- front_ = back_;
|
|
|
- size_++;
|
|
|
+ template<typename v_type>
|
|
|
+ void push_back(v_type &&val) {
|
|
|
+ insert_after(iterator(back_, back_ ? back_->left(nullptr) : nullptr), std::forward<v_type>(val));
|
|
|
}
|
|
|
|
|
|
- void push_back(const value_type &&val) {
|
|
|
- XorListNode<value_type> *past_back = back_;
|
|
|
- back_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
- allocator_.construct(back_, XorListNode<T>(std::forward<XorListNode<T> >(val)));
|
|
|
- back_->assign_leftright(past_back, nullptr);
|
|
|
- if (past_back)
|
|
|
- past_back->assign_leftright(past_back->left(nullptr), back_);
|
|
|
- if (!front_)
|
|
|
- front_ = back_;
|
|
|
- size_++;
|
|
|
+ template<typename v_type>
|
|
|
+ void push_front(v_type &&val) {
|
|
|
+ insert_before(iterator(front_, nullptr), std::forward<v_type>(val));
|
|
|
}
|
|
|
|
|
|
- void push_front(const value_type &val) {
|
|
|
- XorListNode<value_type> *past_front = front_;
|
|
|
- front_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
- allocator_.construct(front_, std::forward<XorListNode<T> >(val));
|
|
|
- front_->assign_leftright(nullptr, past_front);
|
|
|
- if (past_front)
|
|
|
- past_front->assign_leftright(front_, past_front->right(nullptr));
|
|
|
- if (!back_)
|
|
|
- back_ = front_;
|
|
|
- size_++;
|
|
|
+ template<typename v_type>
|
|
|
+ void insert_before(iterator it, v_type &&val) {
|
|
|
+ _m_insert(it, std::forward<v_type>(val), BEFORE);
|
|
|
}
|
|
|
|
|
|
- void push_front(const value_type &&val) {
|
|
|
- XorListNode<value_type> *past_front = front_;
|
|
|
- front_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
- allocator_.construct(front_, std::forward<XorListNode<T> >(val));
|
|
|
- front_->assign_leftright(nullptr, past_front);
|
|
|
- if (past_front)
|
|
|
- past_front->assign_leftright(front_, past_front->right(nullptr));
|
|
|
- if (!back_)
|
|
|
- back_ = front_;
|
|
|
- size_++;
|
|
|
+ template<typename v_type>
|
|
|
+ void insert_after(iterator it, v_type &&val) {
|
|
|
+ _m_insert(it, std::forward<v_type>(val), AFTER);
|
|
|
}
|
|
|
|
|
|
void pop_back() {
|
|
|
- XorListNode<T> *past_back = back_;
|
|
|
- back_ = back_->left(nullptr);
|
|
|
- back_->assign_leftright(back_->left(past_back), nullptr);
|
|
|
- allocator_.destroy(past_back);
|
|
|
- allocator_.deallocate(past_back, 1);
|
|
|
+ if (!back_)
|
|
|
+ return;
|
|
|
+ erase(iterator(back_, back_->left(nullptr)));
|
|
|
}
|
|
|
|
|
|
void pop_front() {
|
|
|
- XorListNode<T> *past_front = front_;
|
|
|
- front_ = front_->right(nullptr);
|
|
|
- front_->assign_leftright(nullptr, front_->right(past_front));
|
|
|
- allocator_.destroy(past_front);
|
|
|
- allocator_.deallocate(past_front, 1);
|
|
|
+ if (!front_)
|
|
|
+ return;
|
|
|
+ erase(iterator(front_, nullptr));
|
|
|
}
|
|
|
|
|
|
- void insert_before(iterator it, T &val) {
|
|
|
- XorListNode<T> *cur = *it;
|
|
|
- XorListNode<T> *prev = it.left_;
|
|
|
- XorListNode<T> *past = it.node_->right(prev);
|
|
|
-
|
|
|
- XorListNode<T> *new_node = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
- allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
|
|
|
- new_node->assign_leftright(prev, cur);
|
|
|
+ void erase(iterator it) {
|
|
|
+ XorListNode<T> *left = it.left_;
|
|
|
+ XorListNode<T> *cur = it.node_;
|
|
|
+ XorListNode<T> *right = it.node_->right(left);
|
|
|
|
|
|
- if (cur)
|
|
|
- cur->assign_leftright(new_node, past);
|
|
|
+ if (left)
|
|
|
+ left->assign_leftright(left->left(cur), right);
|
|
|
|
|
|
- if (prev)
|
|
|
- prev->assign_leftright(prev->left(cur), new_node);
|
|
|
- }
|
|
|
+ if (right)
|
|
|
+ right->assign_leftright(left, right->right(cur));
|
|
|
|
|
|
- void insert_before(iterator it, T &&val) {
|
|
|
- XorListNode<T> *cur = *it;
|
|
|
- XorListNode<T> *prev = it.left_;
|
|
|
- XorListNode<T> *past = it.node_->right(prev);
|
|
|
+ if (cur) {
|
|
|
+ size_--;
|
|
|
+ if (front_ == cur)
|
|
|
+ front_ = cur->right(nullptr);
|
|
|
+ if (back_ == cur)
|
|
|
+ back_ = cur->left(nullptr);
|
|
|
+ }
|
|
|
|
|
|
- XorListNode<T> *new_node = allocator_.allocate(1);
|
|
|
- allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
|
|
|
- new_node->assign_leftright(prev, cur);
|
|
|
+ allocator_.destroy(cur);
|
|
|
+ allocator_.deallocate(cur, 1);
|
|
|
+ }
|
|
|
|
|
|
- if (cur)
|
|
|
- cur->assign_leftright(new_node, past);
|
|
|
+ void clear() {
|
|
|
+ XorListNode<T> *xleft = nullptr;
|
|
|
+ XorListNode<T> *x = front_;
|
|
|
+ while (x != back_) {
|
|
|
+ XorListNode<T> *xnext = x->right(xleft);
|
|
|
+ if (xnext) {
|
|
|
+ allocator_.destroy(xleft);
|
|
|
+ allocator_.deallocate(xleft, 1);
|
|
|
+ }
|
|
|
+ xleft = x;
|
|
|
+ x = xnext;
|
|
|
+ }
|
|
|
|
|
|
- if (prev)
|
|
|
- prev->assign_leftright(prev->left(cur), new_node);
|
|
|
+ if (xleft) {
|
|
|
+ allocator_.destroy(xleft);
|
|
|
+ allocator_.deallocate(xleft, 1);
|
|
|
+ }
|
|
|
+ if (x) {
|
|
|
+ allocator_.destroy(x);
|
|
|
+ allocator_.deallocate(x, 1);
|
|
|
+ }
|
|
|
+ size_ = 0;
|
|
|
+ front_ = back_ = nullptr;
|
|
|
}
|
|
|
|
|
|
- void insert_after(iterator it, T &val) {
|
|
|
- XorListNode<T> *cur = *it;
|
|
|
- XorListNode<T> *prev = it.left_;
|
|
|
- XorListNode<T> *past = it.node_->right(prev);
|
|
|
-
|
|
|
- XorListNode<T> *new_node = allocator_.allocate(1);
|
|
|
- allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
|
|
|
- new_node->assign_leftright(cur, past);
|
|
|
+private:
|
|
|
+ enum E_POSITION_TYPE {
|
|
|
+ BEFORE,
|
|
|
+ AFTER
|
|
|
+ };
|
|
|
|
|
|
- if (cur)
|
|
|
- cur->assign_leftright(prev, new_node);
|
|
|
+ template<typename v_type>
|
|
|
+ void _m_insert(iterator it, v_type &&val, E_POSITION_TYPE pos) {
|
|
|
+ XorListNode<T> *cur = it.node_;
|
|
|
+ XorListNode<T> *left = it.left_;
|
|
|
|
|
|
- if (past)
|
|
|
- past->assign_leftright(new_node, past->right(cur));
|
|
|
- }
|
|
|
+ XorListNode<T> *new_node = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
|
|
|
+ Node_alloc_traits::construct(allocator_, new_node, std::forward<v_type>(val));
|
|
|
+ new_node->assign_leftright(nullptr, nullptr);
|
|
|
|
|
|
- void insert_after(iterator it, T &&val) {
|
|
|
- XorListNode<T> *cur = *it;
|
|
|
- XorListNode<T> *prev = it.left_;
|
|
|
- XorListNode<T> *past = it.node_->right(prev);
|
|
|
+ if (!front_ || !back_) {
|
|
|
+ front_ = back_ = new_node;
|
|
|
+ size_ = 1;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- XorListNode<T> *new_node = allocator_.allocate(1);
|
|
|
- allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
|
|
|
- new_node->assign_leftright(cur, past);
|
|
|
+ XorListNode<T> *right = it.node_->right(left);
|
|
|
|
|
|
- if (cur)
|
|
|
- cur->assign_leftright(prev, new_node);
|
|
|
|
|
|
- if (past)
|
|
|
- past->assign_leftright(new_node, past->right(cur));
|
|
|
- }
|
|
|
+ if (pos == BEFORE) {
|
|
|
+ new_node->assign_leftright(left, cur);
|
|
|
+ cur->assign_leftright(new_node, right);
|
|
|
|
|
|
- void erase(iterator it) {
|
|
|
- XorListNode<T> *prev = it.left_;
|
|
|
- XorListNode<T> *cur = it.operator->();
|
|
|
- XorListNode<T> *past = it.node_->right(prev);
|
|
|
+ if (left)
|
|
|
+ left->assign_leftright(left->left(cur), new_node);
|
|
|
|
|
|
- if (prev)
|
|
|
- prev->assign_leftright(prev->left(cur), past);
|
|
|
+ if (cur == front_)
|
|
|
+ front_ = new_node;
|
|
|
+ }
|
|
|
|
|
|
- if (past)
|
|
|
- past->assign_leftright(prev, past->right(cur));
|
|
|
+ if (pos == AFTER) {
|
|
|
+ new_node->assign_leftright(cur, right);
|
|
|
+ cur->assign_leftright(left, new_node);
|
|
|
|
|
|
- if (cur)
|
|
|
- size_--;
|
|
|
+ if (right)
|
|
|
+ right->assign_leftright(new_node, right->right(cur));
|
|
|
|
|
|
- allocator_.destroy(cur);
|
|
|
- allocator_.deallocate(cur, 1);
|
|
|
+ if (cur == back_)
|
|
|
+ back_ = new_node;
|
|
|
+ }
|
|
|
+ size_++;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
private:
|
|
|
XorListNode<T> *front_;
|
|
|
XorListNode<T> *back_; // Pointer to the LAST element
|
|
|
|
|
|
size_type size_;
|
|
|
- allocator_type allocator_;
|
|
|
+ Node_alloc_type allocator_;
|
|
|
|
|
|
};
|
|
|
|