Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <iterator>
- #include <memory>
- #include <stdexcept>
- template <typename T>
- class MyList {
- friend std::ostream& operator<<(std::ostream& os, const MyList& list) {
- if (list.list_size == 0) {
- os << "The list is empty\n";
- }
- else {
- os << "List elements:\n";
- for (auto i : list) {
- os << '\t' << i << std::endl;
- }
- }
- return os;
- }
- private:
- struct Node {
- T data;
- std::unique_ptr<Node> next;
- Node(T data) : data{ data }, next{ nullptr } {}
- };
- std::unique_ptr<Node> head;
- size_t list_size{ 0 };
- public:
- MyList() : head{ nullptr } {}
- ~MyList() { clear(); }
- void push_front(const T& value) {
- std::unique_ptr<Node> newNode{ std::make_unique<Node>(value) };
- newNode->next = std::move(head);
- head = std::move(newNode);
- ++list_size;
- }
- T pop_front() {
- if (head == nullptr) {
- throw std::out_of_range("Cannot pop from an empty list");
- }
- T data{ std::move(head->data) };
- head = std::move(head->next);
- --list_size;
- return data;
- }
- T& front() {
- if (head == nullptr) {
- throw std::out_of_range("List is empty");
- }
- return head->data;
- }
- const T& front() const {
- if (head == nullptr) {
- throw std::out_of_range("List is empty");
- }
- return head->data;
- }
- void clear() {
- while (head != nullptr) {
- head = std::move(head->next);
- --list_size;
- }
- }
- size_t size() const { return list_size; }
- void remove(const T& value) {
- while (head != nullptr && head->data == value) {
- head = std::move(head->next);
- --list_size;
- }
- Node* current{ head.get() };
- while (current && current->next) {
- if (current->next->data == value) {
- current->next = std::move(current->next->next);
- --list_size;
- }
- else {
- current = current->next.get();
- }
- }
- }
- class ConstIterator {
- private:
- const Node* current;
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = T;
- using pointer = const T*;
- using reference = const T&;
- using iterator_category = std::forward_iterator_tag;
- ConstIterator(const Node* node) : current{ node } {}
- ConstIterator& operator++() {
- if (current) {
- current = current->next.get();
- }
- return *this;
- }
- ConstIterator operator++(int) {
- ConstIterator tmp = *this;
- ++(*this);
- return tmp;
- }
- reference operator*() const {
- if (!current) {
- throw std::out_of_range("Dereferencing a null iterator");
- }
- return current->data;
- }
- pointer operator->() const {
- if (!current) {
- throw std::out_of_range("Dereferencing a null iterator");
- }
- return ¤t->data;
- }
- bool operator!=(const ConstIterator& other) const {
- return current != other.current;
- }
- bool operator==(const ConstIterator& other) const {
- return current == other.current;
- }
- };
- ConstIterator begin() const {
- return ConstIterator(head.get());
- }
- ConstIterator end() const {
- return ConstIterator(nullptr);
- }
- // Iterator
- class Iterator {
- Node* current;
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = T;
- using pointer = T*;
- using reference = T&;
- using iterator_category = std::forward_iterator_tag;
- Iterator(Node* node) : current{ node } {}
- Iterator& operator++() {
- if (current) {
- current = current->next.get();
- }
- return *this;
- }
- Iterator operator++(int) {
- Iterator tmp = *this;
- ++(*this);
- return tmp;
- }
- reference operator*() const {
- if (!current) {
- throw std::out_of_range("Dereferencing a null iterator");
- }
- return current->data;
- }
- pointer operator->() const {
- if (!current) {
- throw std::out_of_range("Dereferencing a null iterator");
- }
- return ¤t->data;
- }
- bool operator!=(const Iterator& other) const {
- return current != other.current;
- }
- bool operator==(const Iterator& other) const {
- return current == other.current;
- }
- };
- Iterator begin() {
- return Iterator(head.get());
- }
- Iterator end() {
- return Iterator(nullptr);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement