Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cassert>
- #include <cstddef>
- #include <iterator>
- #include <string>
- #include <utility>
- #include <algorithm>
- template <typename Type>
- class SingleLinkedList {
- struct Node {
- Node() = default;
- Node(const Type& val, Node* next) : value(val), next_node(next) {}
- Type value;
- Node* next_node = nullptr;
- };
- template <typename ValueType>
- class BasicIterator {
- friend class SingleLinkedList;
- explicit BasicIterator(Node* node) {
- node_ = node;
- }
- public:
- using iterator_category = std::forward_iterator_tag;
- using value_type = Type;
- using difference_type = std::ptrdiff_t;
- using pointer = ValueType*;
- using reference = ValueType&;
- BasicIterator() = default;
- BasicIterator(const BasicIterator<Type>& other) noexcept {
- node_ = other.node_;
- }
- BasicIterator& operator=(const BasicIterator& rhs) = default;
- [[nodiscard]] bool operator==(const BasicIterator<const Type>& rhs) const noexcept {
- return node_ == rhs.node_;
- }
- [[nodiscard]] bool operator!=(const BasicIterator<const Type>& rhs) const noexcept {
- return node_ != rhs.node_;
- }
- [[nodiscard]] bool operator==(const BasicIterator<Type>& rhs) const noexcept {
- return node_ == rhs.node_;
- }
- [[nodiscard]] bool operator!=(const BasicIterator<Type>& rhs) const noexcept {
- return node_ != rhs.node_;
- }
- BasicIterator& operator++() noexcept {
- node_ = node_->next_node;
- return *this;
- }
- BasicIterator operator++(int) noexcept {
- auto old_value(*this);
- ++(*this);
- return old_value;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return node_->value;
- }
- [[nodiscard]] pointer operator->() const noexcept {
- if(node_){
- return &node_->value;
- }else{
- return nullptr;
- }
- }
- private:
- Node* node_ = nullptr;
- };
- public:
- SingleLinkedList() {}
- template <typename TypeIt>
- void Init(TypeIt begin, TypeIt end) {
- Node* node = &head_;
- for (TypeIt i= begin;i!=end; ++i) {
- ++size_;
- node->next_node = new Node(*i, nullptr);
- node = node->next_node;
- }
- }
- SingleLinkedList(std::initializer_list<Type> values) {
- SingleLinkedList helper;
- helper.Init(values.begin(), values.end());
- swap(helper);
- }
- SingleLinkedList(const SingleLinkedList& other) {
- SingleLinkedList helper;
- helper.Init(other.begin(), other.end());
- swap(helper);
- }
- SingleLinkedList& operator=(const SingleLinkedList& rhs) {
- if(this!= &rhs){
- SingleLinkedList helper(rhs);
- swap(helper);
- }
- return *this;
- }
- using value_type = Type;
- using reference = value_type&;
- using const_reference = const value_type&;
- using Iterator = BasicIterator<Type>;
- using ConstIterator = BasicIterator<const Type>;
- [[nodiscard]] Iterator begin() noexcept {
- return Iterator{head_.next_node};
- }
- [[nodiscard]] Iterator end() noexcept {
- return Iterator{nullptr};
- }
- [[nodiscard]] ConstIterator begin() const noexcept {
- return ConstIterator{head_.next_node};
- }
- [[nodiscard]] ConstIterator end() const noexcept {
- return ConstIterator{nullptr};
- }
- [[nodiscard]] ConstIterator cbegin() const noexcept {
- return ConstIterator{head_.next_node};
- }
- [[nodiscard]] ConstIterator cend() const noexcept {
- return ConstIterator{nullptr};
- }
- [[nodiscard]] size_t GetSize() const noexcept {
- return size_;
- }
- [[nodiscard]] bool IsEmpty() const noexcept {
- if (!size_) {
- return true;
- }
- return false;
- }
- void PushFront(const Type& value) {
- head_.next_node = new Node(value, head_.next_node);
- ++size_;
- }
- void Clear() noexcept {
- while (head_.next_node) {
- Node* new_head = head_.next_node->next_node;
- delete head_.next_node;
- head_.next_node = new_head;
- }
- size_ = 0;
- }
- void swap(SingleLinkedList& other) noexcept {
- std::swap(head_.next_node, other.head_.next_node);
- std::swap(size_, other.size_);
- }
- ~SingleLinkedList() {
- Clear();
- }
- private:
- Node head_;
- size_t size_ = 0;
- };
- template <typename Type>
- void swap(SingleLinkedList<Type>& lhs, SingleLinkedList<Type>& rhs) noexcept {
- lhs.swap(rhs);
- }
- template <typename Type>
- bool operator==(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- template <typename Type>
- bool operator!=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return !(lhs==rhs);
- }
- template <typename Type>
- bool operator<(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- template <typename Type>
- bool operator<=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return !(rhs < lhs);
- }
- template <typename Type>
- bool operator>(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return rhs <lhs;
- }
- template <typename Type>
- bool operator>=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
- return !(lhs <rhs);
- }
- void Test3() {
- {
- SingleLinkedList<int> list_1;
- list_1.PushFront(1);
- list_1.PushFront(2);
- SingleLinkedList<int> list_2;
- list_2.PushFront(1);
- list_2.PushFront(2);
- list_2.PushFront(3);
- SingleLinkedList<int> list_1_copy;
- list_1_copy.PushFront(1);
- list_1_copy.PushFront(2);
- SingleLinkedList<int> empty_list;
- SingleLinkedList<int> another_empty_list;
- assert(list_1 == list_1);
- assert(empty_list == empty_list);
- assert(list_1 == list_1_copy);
- assert(list_1 != list_2);
- assert(list_2 != list_1);
- assert(empty_list == another_empty_list);
- }
- {
- SingleLinkedList<int> first;
- first.PushFront(1);
- first.PushFront(2);
- SingleLinkedList<int> second;
- second.PushFront(10);
- second.PushFront(11);
- second.PushFront(15);
- const auto old_first_begin = first.begin();
- const auto old_second_begin = second.begin();
- const auto old_first_size = first.GetSize();
- const auto old_second_size = second.GetSize();
- first.swap(second);
- assert(second.begin() == old_first_begin);
- assert(first.begin() == old_second_begin);
- assert(second.GetSize() == old_first_size);
- assert(first.GetSize() == old_second_size);
- {
- using std::swap;
- swap(first, second);
- assert(first.begin() == old_first_begin);
- assert(second.begin() == old_second_begin);
- assert(first.GetSize() == old_first_size);
- assert(second.GetSize() == old_second_size);
- }
- }
- {
- SingleLinkedList<int> list{1, 2, 3, 4, 5};
- assert(list.GetSize() == 5);
- assert(!list.IsEmpty());
- assert(std::equal(list.begin(), list.end(), std::begin({1, 2, 3, 4, 5})));
- }
- {
- using IntList = SingleLinkedList<int>;
- assert((IntList{1, 2, 3} < IntList{1, 2, 3, 1}));
- assert((IntList{1, 2, 3} <= IntList{1, 2, 3}));
- assert((IntList{1, 2, 4} > IntList{1, 2, 3}));
- assert((IntList{1, 2, 3} >= IntList{1, 2, 3}));
- }
- {
- const SingleLinkedList<int> empty_list{};
- {
- auto list_copy(empty_list);
- assert(list_copy.IsEmpty());
- }
- SingleLinkedList<int> non_empty_list{1, 2, 3, 4};
- {
- auto list_copy(non_empty_list);
- assert(non_empty_list.begin() != list_copy.begin());
- assert(list_copy == non_empty_list);
- }
- }
- {
- const SingleLinkedList<int> source_list{1, 2, 3, 4};
- SingleLinkedList<int> receiver{5, 4, 3, 2, 1};
- receiver = source_list;
- assert(receiver.begin() != source_list.begin());
- assert(receiver == source_list);
- }
- struct ThrowOnCopy {
- ThrowOnCopy() = default;
- explicit ThrowOnCopy(int& copy_counter) noexcept
- : countdown_ptr(©_counter) {
- }
- ThrowOnCopy(const ThrowOnCopy& other)
- : countdown_ptr(other.countdown_ptr) //
- {
- if (countdown_ptr) {
- if (*countdown_ptr == 0) {
- throw std::bad_alloc();
- } else {
- --(*countdown_ptr);
- }
- }
- }
- ThrowOnCopy& operator=(const ThrowOnCopy& rhs) = delete;
- int* countdown_ptr = nullptr;
- };
- {
- SingleLinkedList<ThrowOnCopy> src_list;
- src_list.PushFront(ThrowOnCopy{});
- src_list.PushFront(ThrowOnCopy{});
- auto thrower = src_list.begin();
- src_list.PushFront(ThrowOnCopy{});
- int copy_counter = 0;
- thrower->countdown_ptr = ©_counter;
- SingleLinkedList<ThrowOnCopy> dst_list;
- dst_list.PushFront(ThrowOnCopy{});
- int dst_counter = 10;
- dst_list.begin()->countdown_ptr = &dst_counter;
- dst_list.PushFront(ThrowOnCopy{});
- try {
- dst_list = src_list;
- assert(false);
- } catch (const std::bad_alloc&) {
- assert(dst_list.GetSize() == 2);
- auto it = dst_list.begin();
- assert(it != dst_list.end());
- assert(it->countdown_ptr == nullptr);
- ++it;
- assert(it != dst_list.end());
- assert(it->countdown_ptr == &dst_counter);
- assert(dst_counter == 10);
- } catch (...) {
- assert(false);
- }
- }
- }
- int main() {
- Test3();
- }
Advertisement
Add Comment
Please, Sign In to add comment