├── containers_example.png ├── ft_containers.en.subject.pdf ├── templates ├── type1_or_type2.hpp └── stl_like.hpp ├── .vscode └── settings.json ├── main.cpp ├── Makefile ├── README.md ├── iterators ├── list_iterator.hpp ├── rev_list_iterator.hpp ├── vector_iterator.hpp ├── rev_vector_iterator.hpp ├── map_iterator.hpp └── rev_map_iterator.hpp └── containers ├── stack.hpp ├── queue.hpp ├── vector.hpp └── list.hpp /containers_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llefranc/42_ft_containers/HEAD/containers_example.png -------------------------------------------------------------------------------- /ft_containers.en.subject.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llefranc/42_ft_containers/HEAD/ft_containers.en.subject.pdf -------------------------------------------------------------------------------- /templates/type1_or_type2.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* type1_or_type2.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/01/08 16:47:38 by llefranc #+# #+# */ 9 | /* Updated: 2021/02/17 10:49:51 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef TYPE1_OR_TYPE2_HPP 14 | #define TYPE1_OR_TYPE2_HPP 15 | 16 | namespace ft 17 | { 18 | /** 19 | * Use a boolean to typedef either type 1 or type 2. 20 | */ 21 | template 22 | struct chooseConst {}; 23 | 24 | /** 25 | * Typedef: pointer, ref... 26 | */ 27 | template 28 | struct chooseConst 29 | { 30 | typedef isFalse type; 31 | }; 32 | 33 | /** 34 | * Typedef: const pointer, const ref... 35 | */ 36 | template 37 | struct chooseConst 38 | { 39 | typedef isTrue type; 40 | }; 41 | 42 | } //namespace ft 43 | 44 | #endif -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "vector": "cpp", 4 | "__bit_reference": "cpp", 5 | "__config": "cpp", 6 | "__debug": "cpp", 7 | "__errc": "cpp", 8 | "__functional_base": "cpp", 9 | "__hash_table": "cpp", 10 | "__locale": "cpp", 11 | "__mutex_base": "cpp", 12 | "__node_handle": "cpp", 13 | "__nullptr": "cpp", 14 | "__split_buffer": "cpp", 15 | "__string": "cpp", 16 | "__threading_support": "cpp", 17 | "__tuple": "cpp", 18 | "algorithm": "cpp", 19 | "array": "cpp", 20 | "atomic": "cpp", 21 | "bit": "cpp", 22 | "bitset": "cpp", 23 | "cctype": "cpp", 24 | "chrono": "cpp", 25 | "cmath": "cpp", 26 | "complex": "cpp", 27 | "cstdarg": "cpp", 28 | "cstddef": "cpp", 29 | "cstdint": "cpp", 30 | "cstdio": "cpp", 31 | "cstdlib": "cpp", 32 | "cstring": "cpp", 33 | "ctime": "cpp", 34 | "cwchar": "cpp", 35 | "cwctype": "cpp", 36 | "exception": "cpp", 37 | "functional": "cpp", 38 | "initializer_list": "cpp", 39 | "ios": "cpp", 40 | "iosfwd": "cpp", 41 | "iostream": "cpp", 42 | "istream": "cpp", 43 | "iterator": "cpp", 44 | "limits": "cpp", 45 | "locale": "cpp", 46 | "memory": "cpp", 47 | "mutex": "cpp", 48 | "new": "cpp", 49 | "optional": "cpp", 50 | "ostream": "cpp", 51 | "ratio": "cpp", 52 | "sstream": "cpp", 53 | "stdexcept": "cpp", 54 | "streambuf": "cpp", 55 | "string": "cpp", 56 | "string_view": "cpp", 57 | "system_error": "cpp", 58 | "tuple": "cpp", 59 | "type_traits": "cpp", 60 | "typeinfo": "cpp", 61 | "unordered_map": "cpp", 62 | "utility": "cpp", 63 | "__functional_03": "cpp", 64 | "deque": "cpp", 65 | "fstream": "cpp", 66 | "iomanip": "cpp", 67 | "stack": "cpp", 68 | "filesystem": "cpp", 69 | "list": "cpp" 70 | } 71 | } -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* main.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "containers/list.hpp" 21 | #include "containers/vector.hpp" 22 | #include "containers/map.hpp" 23 | #include "containers/stack.hpp" 24 | #include "containers/queue.hpp" 25 | 26 | int main() 27 | { 28 | std::vector std_vec; 29 | std::list std_lis; 30 | std::stack std_sta; 31 | std::stack std_que; 32 | std::map std_map; 33 | 34 | ft::vector ft_vec; 35 | ft::list ft_lis; 36 | ft::stack ft_sta; /* All acting like the real containers from the STL */ 37 | ft::queue ft_que; 38 | ft::map ft_map; 39 | 40 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # **************************************************************************** # 2 | # # 3 | # ::: :::::::: # 4 | # Makefile :+: :+: :+: # 5 | # +:+ +:+ +:+ # 6 | # By: lucaslefrancq This project was code for MACOS. Here is the [subject][1]. 4 | > 5 | *"C++ containers, easy mode"* 6 | 7 | ![Alt text](https://github.com/llefranc/42_ft_containers/blob/main/containers_example.png) 8 | 9 | ## About 10 | 11 | Ft_containers is a project of the mandatory part of the cursus. 12 | It's only made in C++ and was about recoding some containers from the STL. 13 | 14 | In order to succeed, a good comprehension of how **templates**, **iterators**, **containers** and 15 | **algorithms** work was necessary. Of course, STL is not allowed. That means 16 | you cannot use \ or even \. 17 | 18 | Here are the specificities of the five containers: 19 | 20 | - :arrow_right: **Vector:** a dynamic array that allows insertion at the end of the container. Elements can be easily access thanks with the corresponding index, but it's not the most optimal container if a lot of insertion / deletion are needed. 21 | - :arrow_right: **List:** a circular linked list (with a neutral node linking beginning and end of the list). Better than vector for inserting or deleting elements. 22 | - :arrow_right: **Stack:** a container adaptator (LIFO, last in first out). 23 | - :arrow_right: **Queue:** a container adaptator (FIFO, first in first out). 24 | - :arrow_right: **Map:** a sorted container using an AVL binary tree (auto-equilibrates itself to optimize the time to find a value in the tree), in order to store the datas like in a dictionnary (a key associated to its value). 25 | 26 | All my containers use an allocator to manage properly their memory, iterators to access their datas, and handle the same constructors / methods than the containers from the STL in C++98. 27 | 28 | ## Tester 29 | 30 | I created a tester with [Hélène Herin][16], doing several tests on each of the five mandatory containers. It handles over **10000 tests for some containers !** 31 | 32 | It will test all the constructors, methods and iterators, by comparating your containers with the STL containers, and making a diff if some errors occured. 33 | Also, you can choose which tests you want to execute, in the case you're checking specific containers / methods. 34 | 35 | :white_check_mark: If you want to see more, go check it at this repo : https://github.com/llefranc/42_Containator 36 | 37 | ## Sources 38 | 39 | - [Best website for learning about C++ (including C++98)][17] 40 | - [Difference of keywords 'typename' and 'class' in templates][2] 41 | - [Lvalus and rvalues][3] 42 | - [Dependant names in C++][4] 43 | - [What's explicit keyword][5] 44 | - [Explicit call to a constructor][15] 45 | - [Implementing iterators][6] 46 | - [Writing your own STL style container][7] 47 | - [Writing operator++ for iterator][8] 48 | - [Writing operator== for iterator][9] 49 | - [When use typename keyword][10] 50 | - [Cours sur les templates][11] 51 | - [Understanding SFINAE (used in enable_if)][12] 52 | - [How to use the allocator][13] 53 | - [Difference between explicit and implicit copy constructor][14] 54 | 55 | [1]: https://github.com/llefranc/42_ft_containers/blob/main/ft_containers.en.subject.pdf 56 | [2]: https://stackoverflow.com/questions/2023977/difference-of-keywords-typename-and-class-in-templates 57 | [3]: https://www.tutorialspoint.com/What-are-Lvalues-and-Rvalues-in-Cplusplus#:~:text=An%20lvalue%20(locator%20value)%20represents,some%20identifiable%20location%20in%20memory. 58 | [4]: https://stackoverflow.com/questions/1527849/how-do-you-understand-dependent-names-in-c#:~:text=A%20dependent%20name%20is%20essentially,depends%20on%20a%20template%20argument.&text=Names%20that%20depend%20on%20a,at%20the%20point%20of%20definition. 59 | [5]: https://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-mean 60 | [6]: https://stackoverflow.com/questions/8054273/how-to-implement-an-stl-style-iterator-and-avoid-common-pitfalls 61 | [7]: https://stackoverflow.com/questions/7758580/writing-your-own-stl-container/7759622#7759622 62 | [8]: https://stackoverflow.com/questions/4329677/increment-operator-iterator-implementation 63 | [9]: https://stackoverflow.com/questions/12806657/writing-an-operator-function-for-an-iterator-in-c 64 | [10]: https://stackoverflow.com/questions/7923369/when-is-the-typename-keyword-necessary 65 | [11]: https://cpp.developpez.com/cours/cpp/?page=page_14 66 | [12]: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/SFINAE 67 | [13]: https://stackoverflow.com/questions/59539057/c-does-it-lead-to-double-free-when-destroy-element-in-allocatorstring 68 | [14]: https://stackoverflow.com/questions/1051379/is-there-a-difference-between-copy-initialization-and-direct-initialization 69 | [15]: https://stackoverflow.com/questions/12036037/explicit-call-to-a-constructor 70 | [16]: https://github.com/hherin 71 | [17]: http://www.cplusplus.com/ 72 | -------------------------------------------------------------------------------- /iterators/list_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* list_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/01/07 15:06:15 by llefranc #+# #+# */ 9 | /* Updated: 2021/03/09 13:31:40 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef LIST_ITERATOR_HPP 14 | #define LIST_ITERATOR_HPP 15 | 16 | #include "../templates/type1_or_type2.hpp" 17 | 18 | namespace ft 19 | { 20 | template 21 | class rev_list_iterator; 22 | 23 | 24 | /** 25 | * ------------------------------------------------------------- * 26 | * -------------------- FT::LIST_ITERATOR -------------------- * 27 | * 28 | * - Coplien form: 29 | * (constructor): Construct list_iterator 30 | * (destructor): List_iterator destructor 31 | * operator=: Assign content 32 | * 33 | * - Operators 34 | * operators: Operators for list_iterator 35 | * non-member operators: Operators for list_iterator 36 | * ------------------------------------------------------------- * 37 | */ 38 | 39 | /** 40 | * @param T Type of container's elements. 41 | * @param Node The structure used as nodes in the list. 42 | * @param B Boolean to indicate if it's an iterator / a const iterator. 43 | */ 44 | template 45 | class list_iterator 46 | { 47 | /* ------------------------------------------------------------- */ 48 | /* -------------------------- ALIASES -------------------------- */ 49 | 50 | public: 51 | 52 | typedef long int difference_type; 53 | typedef T value_type; 54 | typedef size_t size_type; 55 | 56 | typedef std::bidirectional_iterator_tag iterator_category; 57 | typedef typename chooseConst::type reference; 58 | typedef typename chooseConst::type pointer; 59 | typedef Node* nodePtr; 60 | 61 | 62 | /* ------------------------------------------------------------- */ 63 | /* ------------------------- ATTRIBUTES ------------------------ */ 64 | 65 | private: 66 | 67 | nodePtr _node; // A pointer to a node in the list. 68 | 69 | 70 | /* ------------------------------------------------------------- */ 71 | /* ------------------------ COPLIEN FORM ----------------------- */ 72 | 73 | public: 74 | 75 | /** 76 | * Default constructor, creates a list_iterator pointing to a node. 77 | * 78 | * @param node A pointer to a node containing a T element. Value initialized if not provided. 79 | */ 80 | list_iterator(nodePtr node = 0) : _node(node) {} 81 | 82 | /** 83 | * Copy constructor : creates a const list_iterator pointing to the same node. 84 | * Convert constructor : creates a list_iterator from a const list_iterator, 85 | * pointing to the same node. 86 | * 87 | * @param copy The iterator that will be copied. 88 | */ 89 | list_iterator(const list_iterator& copy) { _node = copy.getNode(); } 90 | 91 | ~list_iterator() {} 92 | 93 | /** 94 | * Assigns a list_iterator to this list_iterator. Both iterators will point to the 95 | * same node. 96 | * 97 | * @param x The list_iterator that will be assigned. 98 | */ 99 | list_iterator& operator=(const list_iterator& assign) 100 | { 101 | if (this != &assign) 102 | _node = assign._node; 103 | return (*this); 104 | } 105 | 106 | 107 | /* ------------------------------------------------------------- */ 108 | /* --------------------------- GETTERS ------------------------- */ 109 | 110 | /** 111 | * @return A non constant pointer to the actual node that the iterator is 112 | * pointing to. 113 | */ 114 | nodePtr getNode() const { return _node; } 115 | 116 | 117 | /* ------------------------------------------------------------- */ 118 | /* ---------------------- OPERATOR OVERLOADS ------------------- */ 119 | 120 | reference operator*() const { return (_node->content); } 121 | pointer operator->() const { return (&(_node->content)); } 122 | 123 | list_iterator& operator++() { _node = _node->next; return (*this); } 124 | list_iterator operator++(int) { list_iterator res(*this); ++(*this); return (res); }; 125 | list_iterator& operator--() { _node = _node->prev; return (*this); } 126 | list_iterator operator--(int) { list_iterator res(*this); --(*this); return (res); }; 127 | 128 | 129 | /* ------------------------------------------------------------- */ 130 | /* --------------- NON-MEMBER OPERATOR OVERLOADS --------------- */ 131 | 132 | bool operator==(const list_iterator& it) const { return (it._node == _node); } 133 | bool operator!=(const list_iterator& it) const { return (it._node != _node); } 134 | 135 | }; // class list_iterator 136 | 137 | } // namespace ft 138 | 139 | #endif -------------------------------------------------------------------------------- /iterators/rev_list_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* rev_list_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq 42 | class rev_list_iterator 43 | { 44 | /* ------------------------------------------------------------- */ 45 | /* -------------------------- ALIASES -------------------------- */ 46 | 47 | public: 48 | 49 | typedef long int difference_type; 50 | typedef T value_type; 51 | typedef size_t size_type; 52 | 53 | typedef std::bidirectional_iterator_tag iterator_category; 54 | typedef typename chooseConst::type reference; 55 | typedef typename chooseConst::type pointer; 56 | typedef Node* nodePtr; 57 | 58 | 59 | /* ------------------------------------------------------------- */ 60 | /* ------------------------- ATTRIBUTES ------------------------ */ 61 | 62 | private: 63 | 64 | nodePtr _node; // A pointer to a node in the list 65 | 66 | 67 | /* ------------------------------------------------------------- */ 68 | /* ------------------------ COPLIEN FORM ----------------------- */ 69 | 70 | public: 71 | 72 | /** 73 | * Default constructor, creates a rev_list_iterator pointing to a node. 74 | * 75 | * @param node A pointer to node containing a T element. Value initialized if not provided. 76 | */ 77 | rev_list_iterator(nodePtr node = 0) : _node(node) {} 78 | 79 | /** 80 | * Copy constructor : creates a const rev_list_iterator pointing to the same node. 81 | * Convert constructor : creates a rev_list_iterator from a const rev_list_iterator, 82 | * pointing to the same node. 83 | * 84 | * @param copy The iterator that will be copied. 85 | */ 86 | rev_list_iterator(const rev_list_iterator& copy) { _node = copy.getNode(); } 87 | 88 | /** 89 | * Convert constructor : creates a rev_list_iterator from a const / not const 90 | * list_iterator, pointing to the previous T element. This is necessary so 91 | * begin() == rend(), and end == rbegin(). 92 | * 93 | * @param copy The list_iterator that will be converted. 94 | */ 95 | rev_list_iterator(const list_iterator& copy) { _node = copy.getNode()->prev; } 96 | 97 | ~rev_list_iterator() {} 98 | 99 | /** 100 | * Assigns a rev_list_iterator to this rev_list_iterator. Both iterators will point to the 101 | * same node. 102 | * 103 | * @param x The rev_list_iterator that will be assigned. 104 | */ 105 | rev_list_iterator& operator=(const rev_list_iterator& assign) 106 | { 107 | if (this != &assign) 108 | _node = assign._node; 109 | return (*this); 110 | } 111 | 112 | 113 | /* ------------------------------------------------------------- */ 114 | /* --------------------------- GETTERS ------------------------- */ 115 | 116 | /** 117 | * @return A non constant pointer to the actual node that the iterator is 118 | * pointing to. 119 | */ 120 | nodePtr getNode() const { return _node; } 121 | 122 | 123 | /* ------------------------------------------------------------- */ 124 | /* ---------------------- OPERATOR OVERLOADS ------------------- */ 125 | 126 | reference operator*() const { return (_node->content); } 127 | pointer operator->() const { return (&_node->content); } 128 | 129 | rev_list_iterator& operator++() { _node = _node->prev; return (*this); } 130 | rev_list_iterator operator++(int) { rev_list_iterator res(*this); ++(*this); return (res); }; 131 | rev_list_iterator& operator--() { _node = _node->next; return (*this); } 132 | rev_list_iterator operator--(int) { rev_list_iterator res(*this); --(*this); return (res); }; 133 | 134 | 135 | /* ------------------------------------------------------------- */ 136 | /* --------------- NON-MEMBER OPERATOR OVERLOADS --------------- */ 137 | 138 | bool operator==(const rev_list_iterator& it) const { return (it._node == _node); } 139 | bool operator!=(const rev_list_iterator& it) const { return (it._node != _node); } 140 | 141 | }; // class rev_list_iterator 142 | 143 | } // namespace ft 144 | 145 | #endif -------------------------------------------------------------------------------- /containers/stack.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* stack.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq > 46 | class stack 47 | { 48 | /* ------------------------------------------------------------- */ 49 | /* -------------------------- ALIASES -------------------------- */ 50 | 51 | public: 52 | 53 | typedef T value_type; 54 | typedef Container container_type; 55 | typedef size_t size_type; 56 | 57 | 58 | /* ------------------------------------------------------------- */ 59 | /* ------------------------- ATTRIBUTES ------------------------ */ 60 | 61 | private: 62 | 63 | container_type _ctnr; // Underlying container object (either a vector, a list or a 64 | // deque) where the elements are stored. 65 | 66 | /* ------------------------------------------------------------- */ 67 | /* ------------------------ COPLIEN FORM ----------------------- */ 68 | 69 | public: 70 | 71 | /** 72 | * Constructs a stack container adaptor object. It keeps internally a container object 73 | * as data, which is a copy of the ctnr argument passed to the constructor. 74 | * 75 | * @param ctnr The container object to store as data. If no container is pass as argument, 76 | * ctnr calls the default constructor and will be empty. 77 | */ 78 | explicit stack (const container_type& ctnr = container_type()) : 79 | _ctnr(ctnr) {} 80 | 81 | /** 82 | * Copy constructor, creates a stack with the same container object. 83 | * 84 | * @param x The stack that will be copied. 85 | */ 86 | stack(const stack& x) : 87 | _ctnr(x._ctnr) {} 88 | 89 | /** 90 | * This is the destructor of the container object stored as data that 91 | * cleans all the ressources. 92 | */ 93 | ~stack() {} 94 | 95 | /** 96 | * Assigns a stack to this stack. Calls the copy constructor to do the 97 | * assignment(copy and swap idiom). 98 | * 99 | * @param x The stack that will be assigned. 100 | */ 101 | stack& operator=(const stack& x) 102 | { 103 | stack tmp(x); 104 | swap(_ctnr, tmp._ctnr); 105 | return *this; 106 | } 107 | 108 | 109 | /* ------------------------------------------------------------- */ 110 | /* ----------------- MEMBER FUNCTION OVERLOADS ----------------- */ 111 | 112 | /** 113 | * 114 | * Calls member function empty of the underlying container object, which returns 115 | * true if the container is empty. 116 | */ 117 | bool empty() const { return _ctnr.empty(); } 118 | 119 | /** 120 | * 121 | * Calls member function size of the underlying container object, which returns 122 | * container' size. 123 | */ 124 | size_type size() const { return _ctnr.size(); } 125 | 126 | /** 127 | * Calls member function back of the underlying container object, which returns a 128 | * reference to the top element in the stack. Since stacks are last-in first-out 129 | * containers, the top element is the last element inserted into the stack. 130 | */ 131 | value_type& top() { return _ctnr.back(); } 132 | 133 | /** 134 | * Calls member function back of the underlying container object, which returns a 135 | * const reference to the top element in the stack. Since stacks are last-in 136 | * first-out containers, the top element is the last element inserted into the stack. 137 | */ 138 | const value_type& top() const { return _ctnr.back(); } 139 | 140 | /** 141 | * Calls member function push_back of the underlying container object, which inserts 142 | * a new element at the top of the stack. Size is increased by one. 143 | * 144 | * @param val Content of the new element will be initialized to a copy of val. 145 | */ 146 | void push (const value_type& val) { _ctnr.push_back(val); } 147 | 148 | /** 149 | * Calls member function pop_back of the underlying container object, which removes 150 | * the element on top of the stack (latest element inserted), reducing his size by one. 151 | * This calls the removed element's destructor. 152 | */ 153 | void pop() { _ctnr.pop_back(); } 154 | 155 | 156 | /* ------------------------------------------------------------- */ 157 | /* --------------- NON-MEMBER FUNCTION OVERLOADS --------------- */ 158 | 159 | /** 160 | * Performs the appropriate comparison operation between lhs and rhs. 161 | * Each of these operator overloads calls the same operator on the underlying container objects. 162 | */ 163 | 164 | friend bool operator==(const stack& lhs, const stack& rhs) { return lhs._ctnr == rhs._ctnr; } 165 | friend bool operator!=(const stack& lhs, const stack& rhs) { return lhs._ctnr != rhs._ctnr; } 166 | friend bool operator<(const stack& lhs, const stack& rhs) { return lhs._ctnr < rhs._ctnr; } 167 | friend bool operator<=(const stack& lhs, const stack& rhs) { return lhs._ctnr <= rhs._ctnr; } 168 | friend bool operator>(const stack& lhs, const stack& rhs) { return lhs._ctnr > rhs._ctnr; } 169 | friend bool operator>=(const stack& lhs, const stack& rhs) { return lhs._ctnr >= rhs._ctnr; } 170 | 171 | 172 | /* ----------------- PRIVATE MEMBER FUNCTIONS ------------------ */ 173 | /* ------------------------------------------------------------- */ 174 | 175 | private: 176 | 177 | /** 178 | * Swaps two variables. 179 | * 180 | * @param a Will be swap with b. 181 | * @param b Will be swap with a. 182 | */ 183 | template 184 | void swap(U& a, U& b) 185 | { 186 | U tmp(a); 187 | a = b; 188 | b = tmp; 189 | } 190 | 191 | }; // class stack 192 | 193 | } // namespace ft 194 | 195 | #endif -------------------------------------------------------------------------------- /containers/queue.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* queue.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq > 47 | class queue 48 | { 49 | /* ------------------------------------------------------------- */ 50 | /* -------------------------- ALIASES -------------------------- */ 51 | 52 | public: 53 | 54 | typedef T value_type; 55 | typedef Container container_type; 56 | typedef size_t size_type; 57 | 58 | 59 | /* ------------------------------------------------------------- */ 60 | /* ------------------------ ATTRIBUTES ------------------------- */ 61 | 62 | private: 63 | 64 | container_type _ctnr; // Underlying container object (either a list or a deque) 65 | // where the elements are stored. 66 | 67 | /* ------------------------------------------------------------- */ 68 | /* ------------------------ COPLIEN FORM ----------------------- */ 69 | 70 | public: 71 | 72 | /** 73 | * Constructs a queue container adaptor object. It keeps internally a container object 74 | * as data, which is a copy of the ctnr argument passed to the constructor. 75 | * 76 | * @param ctnr The container object to store as data. If no container is pass as argument, 77 | * ctnr calls the default constructor and will be empty. 78 | */ 79 | explicit queue (const container_type& ctnr = container_type()) : 80 | _ctnr(ctnr) {} 81 | 82 | /** 83 | * Copy constructor, creates a queue with the same container object. 84 | * 85 | * @param x The queue that will be copied. 86 | */ 87 | queue(const queue& x) : 88 | _ctnr(x._ctnr) {} 89 | 90 | /** 91 | * This is the destructor of the container object stored as data that 92 | * cleans all the ressources. 93 | */ 94 | ~queue() {} 95 | 96 | /** 97 | * Assigns a queue to this queue. Calls the copy constructor to do the 98 | * assignment(copy and swap idiom). 99 | * 100 | * @param x The queue that will be assigned. 101 | */ 102 | queue& operator=(const queue& x) 103 | { 104 | queue tmp(x); 105 | swap(_ctnr, tmp._ctnr); 106 | return *this; 107 | } 108 | 109 | /* ------------------------------------------------------------- */ 110 | /* ----------------- MEMBER FUNCTION OVERLOADS ----------------- */ 111 | 112 | /** 113 | * 114 | * Calls member function empty of the underlying container object, which returns 115 | * true if the container is empty. 116 | */ 117 | bool empty() const { return _ctnr.empty(); } 118 | 119 | /** 120 | * 121 | * Calls member function size of the underlying container object, which returns 122 | * container' size. 123 | */ 124 | size_type size() const { return _ctnr.size(); } 125 | 126 | /** 127 | * Calls member function front of the underlying container object, which returns a 128 | * reference to the next element in the queue. The next element is the "oldest" element 129 | * in the queue and the same element that is popped out from the queue when queue::pop is called. 130 | */ 131 | value_type& front() { return _ctnr.front(); } 132 | 133 | /** 134 | * Calls member function front of the underlying container object, which returns a const 135 | * reference to the next element in the queue. The next element is the "oldest" element 136 | * in the queue and the same element that is popped out from the queue when queue::pop is called. 137 | */ 138 | const value_type& front() const { return _ctnr.front(); } 139 | 140 | /** 141 | * Calls member function back of the underlying container object, which returns a 142 | * reference to the newest element in the queue (latest element pushed in the queue). 143 | */ 144 | value_type& back() { return _ctnr.back(); } 145 | 146 | /** 147 | * Calls member function back of the underlying container object, which returns a const 148 | * reference to the newest element in the queue (latest element pushed in the queue). 149 | */ 150 | const value_type& back() const { return _ctnr.back(); } 151 | 152 | /** 153 | * Calls member function push_back of the underlying container object, which inserts 154 | * a new element at the end of the queue. Size is increased by one. 155 | * 156 | * @param val Content of the new element will be initialized to a copy of val. 157 | */ 158 | void push (const value_type& val) { _ctnr.push_back(val); } 159 | 160 | /** 161 | * Calls member function pop_front of the underlying container object, which removes 162 | * the oldest element of the queue, reducing his size by one. This calls the removed 163 | * element's destructor. 164 | */ 165 | void pop() { _ctnr.pop_front(); } 166 | 167 | 168 | /* ------------------------------------------------------------- */ 169 | /* --------------- NON-MEMBER FUNCTION OVERLOADS --------------- */ 170 | 171 | /** 172 | * Performs the appropriate comparison operation between lhs and rhs. 173 | * Each of these operator overloads calls the same operator on the underlying container objects. 174 | */ 175 | 176 | friend bool operator==(const queue& lhs, const queue& rhs) { return lhs._ctnr == rhs._ctnr; } 177 | friend bool operator!=(const queue& lhs, const queue& rhs) { return lhs._ctnr != rhs._ctnr; } 178 | friend bool operator<(const queue& lhs, const queue& rhs) { return lhs._ctnr < rhs._ctnr; } 179 | friend bool operator<=(const queue& lhs, const queue& rhs) { return lhs._ctnr <= rhs._ctnr; } 180 | friend bool operator>(const queue& lhs, const queue& rhs) { return lhs._ctnr > rhs._ctnr; } 181 | friend bool operator>=(const queue& lhs, const queue& rhs) { return lhs._ctnr >= rhs._ctnr; } 182 | 183 | 184 | /* ----------------- PRIVATE MEMBER FUNCTIONS ------------------ */ 185 | /* ------------------------------------------------------------- */ 186 | 187 | private: 188 | 189 | /** 190 | * Swaps two variables. 191 | * 192 | * @param a Will be swap with b. 193 | * @param b Will be swap with a. 194 | */ 195 | template 196 | void swap(U& a, U& b) 197 | { 198 | U tmp(a); 199 | a = b; 200 | b = tmp; 201 | } 202 | 203 | }; // class queue 204 | 205 | } // namespace ft 206 | 207 | #endif -------------------------------------------------------------------------------- /templates/stl_like.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* stl_like.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq 17 | #include 18 | 19 | namespace ft 20 | { 21 | /** 22 | * ------------------------------------------------------------- * 23 | * ------------------------- FT::PAIR -------------------------- * 24 | * 25 | * - Coplien form: 26 | * (constructor): Construct pair 27 | * (destructor): Pair destructor 28 | * operator=: Assign content 29 | * 30 | * - Public member variables: 31 | * T1: First pair's member variable 32 | * T2: Second pair's member variable 33 | * ------------------------------------------------------------- * 34 | */ 35 | 36 | template 37 | class pair 38 | { 39 | public: 40 | 41 | /* ------------------------------------------------------------- */ 42 | /* ------------------------ COPLIEN FORM ----------------------- */ 43 | 44 | /** 45 | * Default constructor, value initialized first and second. 46 | */ 47 | pair() : first(), second() {}; 48 | 49 | /** 50 | * Initialization constructor. 51 | * 52 | * @param a Will initialize first. 53 | * @param b Will initialize second. 54 | */ 55 | pair(const T1& a, const T2& b) : first(a), second(b) {}; 56 | 57 | /** 58 | * Copy constructor, creates a pair with the same member variables. 59 | * 60 | * @param copy The pair that will be copied. 61 | */ 62 | pair(const pair& copy) : first(copy.first), second(copy.second) {}; 63 | 64 | /** 65 | * Copy constructor, creates a pair with the same member variables. 66 | * 67 | * @param copy The pair that will be copied. 68 | */ 69 | template 70 | pair(const pair& copy) : first(copy.first), second(copy.second) {}; 71 | 72 | ~pair() {}; 73 | 74 | /** 75 | * Assigns a pair to this pair. 76 | * 77 | * @param assign The pair that will be assigned. 78 | */ 79 | pair& operator=(const pair& assign) 80 | { 81 | if (this != &assign) 82 | { 83 | first = assign.first; 84 | second = assign.second; 85 | } 86 | return (*this); 87 | } 88 | 89 | 90 | /* ------------------------------------------------------------- */ 91 | /* ------------------ PUBLIC MEMBER VARIABLES ------------------ */ 92 | 93 | T1 first; 94 | T2 second; 95 | 96 | }; // pair 97 | 98 | 99 | /** 100 | * ------------------------------------------------------------- * 101 | * ---------------------- FT::ALLOCATOR ------------------------ * 102 | * - Coplien form: 103 | * (constructor) Creates a new allocator instance 104 | * (destructor) Destructs an allocator instance 105 | * 106 | * - Member functions: 107 | * Address Obtains the address of an object 108 | * Allocate Allocates uninitialized storage 109 | * Deallocate Deallocates storage 110 | * Construct Constructs an object in allocated storage 111 | * Destroy Destroys an object in allocated storage 112 | * ------------------------------------------------------------- * 113 | */ 114 | 115 | template 116 | class allocator 117 | { 118 | /* ------------------------------------------------------------- */ 119 | /* --------------------------- ALIASES ------------------------- */ 120 | 121 | public: 122 | 123 | typedef T value_type; 124 | typedef T* pointer; 125 | typedef T& reference; 126 | typedef const T* const_pointer; 127 | typedef const T& const_reference; 128 | typedef size_t size_type; 129 | typedef long int difference_type; 130 | 131 | 132 | /* ------------------------------------------------------------- */ 133 | /* ------------------------ COPLIEN FORM ----------------------- */ 134 | 135 | allocator() throw() {}; 136 | 137 | allocator(const allocator&) throw() {}; 138 | 139 | template 140 | allocator(const allocator&) throw() {}; 141 | 142 | ~allocator() throw() {}; 143 | 144 | 145 | /* ------------------------------------------------------------- */ 146 | /* ---------------------- MEMBER FUNCTIONS --------------------- */ 147 | 148 | /** 149 | * @return The address of x object. 150 | */ 151 | pointer address(reference x) const { return &x; } 152 | 153 | /** 154 | * @return The address of x object. 155 | */ 156 | const_pointer address(const_reference x) const { return &x; } 157 | 158 | 159 | /** 160 | * Allocates uninitialized storage. 161 | * 162 | * @param n The number of objects to allocates. 163 | * @return A pointer to the newly allocated area. 164 | */ 165 | pointer allocate(size_type n) 166 | { 167 | pointer ret; 168 | size_t size = n * sizeof(value_type); 169 | 170 | try 171 | { 172 | ret = reinterpret_cast(::operator new(size)); 173 | } 174 | catch(const std::exception& e) 175 | { 176 | std::cerr << e.what() << '\n'; 177 | } 178 | 179 | return ret; 180 | } 181 | 182 | /** 183 | * Deallocates storage (this doesn't call destructors for the objects present 184 | * in this storage). 185 | * 186 | * @param p The address of a previously allocated area with allocate. 187 | * @param n The size of the area to deallocate. 188 | * @return A pointer to the newly allocated area. 189 | */ 190 | void deallocate (pointer p, size_type n) 191 | { 192 | (void)n; 193 | ::operator delete(p); 194 | } 195 | 196 | /** 197 | * Constructs an object in allocated storage. 198 | * 199 | * @param p A pointer to an unintialized allocated storage. 200 | * @param v The value to use as the copy constructor argument. 201 | */ 202 | void construct(pointer p, const T& v) { new((void*)p)T(v); } 203 | 204 | /** 205 | * Destroy an object in allocated storage. 206 | * 207 | * @param p A pointer to the object that is going to be destroyed. 208 | */ 209 | void destroy(pointer p) { p->~T(); } 210 | 211 | }; // allocator 212 | 213 | 214 | /** 215 | * ------------------------------------------------------------- * 216 | * ------------------------- FT::LESS -------------------------- * 217 | */ 218 | 219 | template 220 | struct less 221 | { 222 | typedef T first_argument_type; 223 | typedef T second_argument_type; 224 | typedef bool result_type; 225 | 226 | bool operator() (const T& x, const T& y) const {return x 241 | struct enable_if {}; 242 | 243 | template <> 244 | struct enable_if { typedef int type; }; 245 | 246 | 247 | /** 248 | * ------------------------------------------------------------- * 249 | * --------------------- FT::IS_INTEGRAL ----------------------- * 250 | */ 251 | 252 | /** 253 | * Value will be true if T is an integral, false otherwise. 254 | */ 255 | template 256 | struct is_integral { static const bool value = false; }; 257 | 258 | template <> 259 | struct is_integral { static const bool value = true; }; 260 | 261 | template <> 262 | struct is_integral { static const bool value = true; }; 263 | 264 | template <> 265 | struct is_integral { static const bool value = true; }; 266 | 267 | template <> 268 | struct is_integral { static const bool value = true; }; 269 | 270 | template <> 271 | struct is_integral { static const bool value = true; }; 272 | 273 | template <> 274 | struct is_integral { static const bool value = true; }; 275 | 276 | template <> 277 | struct is_integral { static const bool value = true; }; 278 | 279 | template <> 280 | struct is_integral { static const bool value = true; }; 281 | 282 | template <> 283 | struct is_integral { static const bool value = true; }; 284 | 285 | template <> 286 | struct is_integral { static const bool value = true; }; 287 | 288 | template <> 289 | struct is_integral { static const bool value = true; }; 290 | 291 | } // namespace ft 292 | 293 | #endif -------------------------------------------------------------------------------- /iterators/vector_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* vector_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/01/05 12:15:29 by llefranc #+# #+# */ 9 | /* Updated: 2021/03/09 13:29:53 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef VECTOR_ITERATOR_HPP 14 | #define VECTOR_ITERATOR_HPP 15 | 16 | #include "../templates/type1_or_type2.hpp" 17 | 18 | // Used in movePtr function 19 | #define ADD 1 20 | #define SUBSTRACT 0 21 | 22 | namespace ft 23 | { 24 | template 25 | class rev_vector_iterator; 26 | 27 | 28 | /** 29 | * ------------------------------------------------------------- * 30 | * -------------------- FT::VECTOR_ITERATOR -------------------- * 31 | * 32 | * - Coplien form: 33 | * (constructor): Construct vector_iterator 34 | * (destructor): Vector_iterator destructor 35 | * operator=: Assign content 36 | * 37 | * - Operators 38 | * operators: Operators for vector_iterator 39 | * non-member operators: Operators for vector_iterator 40 | * ------------------------------------------------------------- * 41 | */ 42 | 43 | /** 44 | * @param T Type of container's elements. 45 | * @param B Boolean to indicate if it's an iterator / a const iterator. 46 | */ 47 | template 48 | class vector_iterator 49 | { 50 | public: 51 | 52 | /* ------------------------------------------------------------- */ 53 | /* -------------------------- ALIASES -------------------------- */ 54 | 55 | typedef long int difference_type; 56 | typedef T value_type; 57 | typedef size_t size_type; 58 | 59 | typedef std::random_access_iterator_tag iterator_category; 60 | typedef typename chooseConst::type reference; 61 | typedef typename chooseConst::type pointer; 62 | typedef T* elemPtr; 63 | 64 | 65 | /* ------------------------------------------------------------- */ 66 | /* ------------------------- ATTRIBUTES ------------------------ */ 67 | 68 | private: 69 | 70 | elemPtr _val; // A pointer to an element in the vector array 71 | 72 | 73 | /* ------------------------------------------------------------- */ 74 | /* ------------------------ COPLIEN FORM ----------------------- */ 75 | 76 | public: 77 | 78 | /** 79 | * Default constructor, creates a vector_iterator pointing to val. 80 | * 81 | * @param val A pointer to a T element. Value initialized if not provided. 82 | */ 83 | vector_iterator(elemPtr val = 0) : 84 | _val(val) {} 85 | 86 | /** 87 | * Copy constructor : creates a const vector_iterator pointing to the same T element. 88 | * Convert constructor : creates a vector_iterator from a const vector_iterator, 89 | * pointing to the same T element. 90 | * 91 | * @param copy The iterator that will be copied. 92 | */ 93 | vector_iterator(const vector_iterator& copy) { _val = copy.getElemPtr(); } 94 | 95 | ~vector_iterator() {} 96 | 97 | /** 98 | * Assign a vector_iterator to this vector_iterator. Both iterators will point to the 99 | * same T element. 100 | * 101 | * @param x The vector_iterator that will be assigned. 102 | */ 103 | vector_iterator& operator=(const vector_iterator& assign) 104 | { 105 | if (this != &assign) 106 | _val = assign._val; 107 | return (*this); 108 | } 109 | 110 | 111 | /* ------------------------------------------------------------- */ 112 | /* --------------------------- GETTERS ------------------------- */ 113 | 114 | /** 115 | * @return A non constant pointer to the actual element that the iterator is 116 | * pointing to. 117 | */ 118 | elemPtr getElemPtr() const { return _val; } 119 | 120 | 121 | /* ------------------------------------------------------------- */ 122 | /* --------------------- OPERATOR OVERLOADS -------------------- */ 123 | 124 | reference operator*() const { return (*_val); } 125 | pointer operator->() const { return (_val); } 126 | 127 | vector_iterator& operator++() { ++_val; return (*this); } 128 | vector_iterator& operator--() { --_val; return (*this); } 129 | 130 | vector_iterator operator++(int) 131 | { 132 | vector_iterator res(*this); 133 | ++(*this); 134 | return (res); 135 | } 136 | 137 | vector_iterator operator--(int) 138 | { 139 | vector_iterator res(*this); 140 | --(*this); 141 | return (res); 142 | } 143 | 144 | bool operator==(const vector_iterator& it) const { return (it._val == _val); } 145 | bool operator!=(const vector_iterator& it) const { return (it._val != _val); } 146 | bool operator<(const vector_iterator& it) const { return (it._val > this->_val); } 147 | bool operator>(const vector_iterator& it) const { return (it._val < this->_val); } 148 | bool operator<=(const vector_iterator& it) const { return (it._val >= this->_val); } 149 | bool operator>=(const vector_iterator& it) const { return (it._val <= this->_val); } 150 | 151 | /** 152 | * Increments 1 time vector_iterator position. 153 | */ 154 | vector_iterator& operator+=(int nb) 155 | { 156 | movePtr(this->_val, nb, ADD); 157 | return (*this); 158 | } 159 | 160 | /** 161 | * Increments nb times vector_iterator position. 162 | */ 163 | vector_iterator operator+(int nb) const 164 | { 165 | vector_iterator it(*this); 166 | 167 | movePtr(it._val, nb, ADD); 168 | return (it); 169 | } 170 | 171 | /** 172 | * Decrements 1 time vector_iterator position. 173 | */ 174 | vector_iterator& operator-=(int nb) 175 | { 176 | movePtr(this->_val, nb, SUBSTRACT); 177 | return (*this); 178 | } 179 | 180 | /** 181 | * Decrements nb times vector_iterator position. 182 | */ 183 | vector_iterator operator-(int nb) const 184 | { 185 | vector_iterator it(*this); 186 | 187 | movePtr(it._val, nb, SUBSTRACT); 188 | return (it); 189 | } 190 | 191 | /** 192 | * @return A reference to vector_iterator + nb. Undefined behavior if the reference 193 | * returned is out of container's range. 194 | */ 195 | reference operator[](int nb) const 196 | { 197 | value_type* tmp(this->_val); 198 | 199 | movePtr(tmp, nb, ADD); 200 | return (*tmp); 201 | } 202 | 203 | /** 204 | * @return The range's lenght between this vector_iterator and another one. 205 | */ 206 | difference_type operator-(vector_iterator it) const 207 | { 208 | return (this->_val - it._val); 209 | } 210 | 211 | 212 | /* ------------------------------------------------------------- */ 213 | /* --------------- NON-MEMBER OPERATOR OVERLOADS --------------- */ 214 | 215 | friend vector_iterator operator+(int nb, const vector_iterator& it) 216 | { 217 | vector_iterator newIt(it); 218 | return (newIt += nb); 219 | } 220 | 221 | friend vector_iterator operator-(int nb, const vector_iterator& it) 222 | { 223 | vector_iterator newIt(it); 224 | return (newIt -= nb); 225 | } 226 | 227 | 228 | /* ------------------------------------------------------------- */ 229 | /* ------------------ PRIVATE MEMBER FUNCTIONS ----------------- */ 230 | 231 | private: 232 | 233 | /** 234 | * Moves random_acces_iterator's pointer. Adapt between addition / substraction 235 | * operation. 236 | * 237 | * @param val The pointer to move. 238 | * @param nb Number of time the pointer will be increased / decreased. 239 | * @param sign Indicate if it's an addition or a substraction. 240 | */ 241 | void movePtr(elemPtr& val, long nb, bool sign) const 242 | { 243 | int mov; 244 | 245 | // If addtion, mov will be positive. If substraction, negative. 246 | if (sign == ADD) 247 | mov = nb > 0 ? mov = 1: mov = -1; 248 | else 249 | mov = nb > 0 ? mov = -1: mov = 1; 250 | 251 | if (nb < 0) 252 | nb *= -1; 253 | for (; nb > 0; --nb) 254 | val += mov; 255 | } 256 | 257 | }; // class vector_iterator 258 | 259 | } // namespace ft 260 | 261 | #endif -------------------------------------------------------------------------------- /iterators/rev_vector_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* rev_vector_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/01/05 12:15:29 by llefranc #+# #+# */ 9 | /* Updated: 2021/03/09 13:29:47 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef REV_VECTOR_ITERATOR_HPP 14 | #define REV_VECTOR_ITERATOR_HPP 15 | 16 | #include "vector_iterator.hpp" 17 | #include "../templates/stl_like.hpp" 18 | 19 | // Used in movePtr function 20 | #define ADD 1 21 | #define SUBSTRACT 0 22 | 23 | namespace ft 24 | { 25 | /** 26 | * ------------------------------------------------------------- * 27 | * ------------------ FT::REV_VECTOR_ITERATOR ------------------ * 28 | * 29 | * - Coplien form: 30 | * (constructor): Construct rev_vector_iterator 31 | * (destructor): Rev_vector_iterator destructor 32 | * operator=: Assign content 33 | * 34 | * - Operators 35 | * operators: Operators for rev_vector_iterator 36 | * non-member operators: Operators for rev_vector_iterator 37 | * ------------------------------------------------------------- * 38 | */ 39 | 40 | /** 41 | * @param T Type of container's elements. 42 | * @param B Boolean to indicate if it's a const or not vector iterator. 43 | */ 44 | template 45 | class rev_vector_iterator 46 | { 47 | public: 48 | 49 | /* ------------------------------------------------------------- */ 50 | /* -------------------------- ALIASES -------------------------- */ 51 | 52 | typedef long int difference_type; 53 | typedef T value_type; 54 | typedef size_t size_type; 55 | 56 | typedef std::random_access_iterator_tag iterator_category; 57 | typedef typename chooseConst::type reference; 58 | typedef typename chooseConst::type pointer; 59 | typedef T* elemPtr; 60 | 61 | 62 | /* ------------------------------------------------------------- */ 63 | /* ------------------------- ATTRIBUTES ------------------------ */ 64 | 65 | private: 66 | 67 | elemPtr _val; // A pointer to an element in the vector array 68 | 69 | 70 | /* ------------------------------------------------------------- */ 71 | /* ------------------------ COPLIEN FORM ----------------------- */ 72 | 73 | public: 74 | 75 | /** 76 | * Default constructor, creates a rev_vector_iterator pointing to val. 77 | * 78 | * @param val A pointer to a T element. Value initialized if not provided. 79 | */ 80 | rev_vector_iterator(elemPtr val = 0) : _val(val) {} 81 | 82 | /** 83 | * Copy constructor : creates a const rev_vector_iterator pointing to the same T element. 84 | * Convert constructor : creates a rev_vector_iterator from a const rev_vector_iterator, 85 | * pointing to the same T element. 86 | * 87 | * @param copy The rev_vector_iterator that will be copied. 88 | */ 89 | rev_vector_iterator(const rev_vector_iterator& copy) { _val = copy.getElemPtr(); } 90 | 91 | /** 92 | * Convert constructor : creates a rev_vector_iterator from a const / not const 93 | * vector_iterator, pointing to the previous T element. This is necessary so 94 | * begin() == rend(), and end == rbegin(). 95 | * 96 | * @param copy The vector_iterator that will be converted. 97 | */ 98 | explicit rev_vector_iterator(const vector_iterator& copy) { _val = copy.getElemPtr() - 1; } 99 | 100 | ~rev_vector_iterator() {} 101 | 102 | /** 103 | * Assign a rev_vector_iterator to this rev_vector_iterator. Both iterators will point to the 104 | * same T element. 105 | * 106 | * @param x The rev_vector_iterator that will be assigned. 107 | */ 108 | rev_vector_iterator& operator=(const rev_vector_iterator& assign) 109 | { 110 | if (this != &assign) 111 | _val = assign._val; 112 | return (*this); 113 | } 114 | 115 | 116 | /* ------------------------------------------------------------- */ 117 | /* --------------------------- GETTERS ------------------------- */ 118 | 119 | /** 120 | * @return A non constant pointer to the actual element that the iterator is 121 | * pointing to. 122 | */ 123 | elemPtr getElemPtr() const { return _val; } 124 | 125 | 126 | /* ------------------------------------------------------------- */ 127 | /* --------------------- OPERATOR OVERLOADS -------------------- */ 128 | 129 | reference operator*() const { return (*_val); } 130 | pointer operator->() const { return (_val); } 131 | 132 | rev_vector_iterator& operator++() { --_val; return (*this); } 133 | rev_vector_iterator& operator--() { ++_val; return (*this); } 134 | 135 | rev_vector_iterator operator++(int) 136 | { 137 | rev_vector_iterator res(*this); 138 | ++(*this); 139 | return (res); 140 | } 141 | 142 | rev_vector_iterator operator--(int) 143 | { 144 | rev_vector_iterator res(*this); 145 | --(*this); 146 | return (res); 147 | } 148 | 149 | bool operator==(const rev_vector_iterator& it) const { return (it._val == _val); } 150 | bool operator!=(const rev_vector_iterator& it) const { return (it._val != _val); } 151 | bool operator<(const rev_vector_iterator& it) const { return (it._val > this->_val); } 152 | bool operator>(const rev_vector_iterator& it) const { return (it._val < this->_val); } 153 | bool operator<=(const rev_vector_iterator& it) const { return (it._val >= this->_val); } 154 | bool operator>=(const rev_vector_iterator& it) const { return (it._val <= this->_val); } 155 | 156 | /** 157 | * Increment 1 time vector_iterator position. 158 | */ 159 | rev_vector_iterator& operator+=(int nb) 160 | { 161 | movePtr(this->_val, nb, ADD); 162 | return (*this); 163 | } 164 | 165 | /** 166 | * Increment nb times vector_iterator position. 167 | */ 168 | rev_vector_iterator operator+(int nb) const 169 | { 170 | rev_vector_iterator it(*this); 171 | 172 | movePtr(it._val, nb, ADD); 173 | return (it); 174 | } 175 | 176 | /** 177 | * Decrement 1 time vector_iterator position. 178 | */ 179 | rev_vector_iterator& operator-=(int nb) 180 | { 181 | movePtr(this->_val, nb, SUBSTRACT); 182 | return (*this); 183 | } 184 | 185 | /** 186 | * Decrement nb times vector_iterator position. 187 | */ 188 | rev_vector_iterator operator-(int nb) const 189 | { 190 | rev_vector_iterator it(*this); 191 | 192 | movePtr(it._val, nb, SUBSTRACT); 193 | return (it); 194 | } 195 | 196 | /** 197 | * @return A reference to rev_vector_iterator + nb. Undefined behavior if the 198 | * reference returned is out of container's range. 199 | */ 200 | reference operator[](int nb) const 201 | { 202 | value_type* tmp(this->_val); 203 | 204 | movePtr(tmp, nb, ADD); 205 | return (*tmp); 206 | } 207 | 208 | /** 209 | * Do a difference between 2 reverse iterators (in the opposite way than normal 210 | * iterators, so that it1 - it2 == rev_it1 - rev_it2). 211 | * 212 | * @return The range's lenght between this rev_vector_iterator and another one. 213 | */ 214 | difference_type operator-(rev_vector_iterator it) const 215 | { 216 | return (it._val - this->_val); 217 | } 218 | 219 | 220 | /* ------------------------------------------------------------- */ 221 | /* ---------------------- FRIEND OPERATORS --------------------- */ 222 | 223 | friend rev_vector_iterator operator+(int nb, const rev_vector_iterator& it) 224 | { 225 | rev_vector_iterator newIt(it); 226 | return (newIt += nb); 227 | } 228 | 229 | friend rev_vector_iterator operator-(int nb, const rev_vector_iterator& it) 230 | { 231 | rev_vector_iterator newIt(it); 232 | return (newIt -= nb); 233 | } 234 | 235 | 236 | /* ------------------------------------------------------------- */ 237 | /* ------------------ PRIVATE MEMBER FUNCTIONS ----------------- */ 238 | 239 | private: 240 | 241 | /** 242 | * Moves rev_vector_acces_iterator's pointer. Adapt between addition / substraction 243 | * operation. 244 | * 245 | * @param val The pointer to move. 246 | * @param nb Number of time the pointer will be increased / decreased. 247 | * @param sign Indicate if it's an addition or a substraction. 248 | */ 249 | void movePtr(elemPtr& val, long nb, bool sign) const 250 | { 251 | int mov; 252 | 253 | // If addtion, mov will be negative. If substraction, positive. 254 | if (sign == ADD) 255 | mov = nb > 0 ? mov = -1: mov = 1; 256 | else 257 | mov = nb > 0 ? mov = 1: mov = -1; 258 | 259 | if (nb < 0) 260 | nb *= -1; 261 | for (; nb > 0; --nb) 262 | val += mov; 263 | } 264 | 265 | }; // class rev_vector_iterator 266 | 267 | } // namespace ft 268 | 269 | #endif -------------------------------------------------------------------------------- /iterators/map_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* map_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/02/10 14:20:22 by llefranc #+# #+# */ 9 | /* Updated: 2021/03/09 13:29:39 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef MAP_ITERATOR 14 | #define MAP_ITERATOR 15 | 16 | #include "../templates/type1_or_type2.hpp" 17 | 18 | namespace ft 19 | { 20 | /** 21 | * ------------------------------------------------------------- * 22 | * ---------------------- FT::MAP_ITERATOR --------------------- * 23 | * 24 | * - Coplien form: 25 | * (constructor): Construct map_iterator 26 | * (destructor): Map_iterator destructor 27 | * operator=: Assign content 28 | * 29 | * - Operators 30 | * operators: Operators for map_iterator 31 | * non-member operators: Operators for map_iterator 32 | * ------------------------------------------------------------- * 33 | */ 34 | 35 | /** 36 | * @param Key Type of container's key elements. 37 | * @param T Type of container's mapped elements. 38 | * @param Compare The predicate used to sort the binary tree. 39 | * @param Node The structure used as nodes in the binary tree. 40 | * @param B Boolean to indicate if it's an iterator / a const iterator. 41 | */ 42 | template 43 | class map_iterator 44 | { 45 | /* ------------------------------------------------------------- */ 46 | /* -------------------------- ALIASES -------------------------- */ 47 | 48 | public: 49 | 50 | typedef Key key_type; 51 | typedef Compare key_compare; 52 | typedef T mapped_type; 53 | 54 | typedef ft::pair value_type; 55 | typedef long int difference_type; 56 | typedef size_t size_type; 57 | 58 | typedef std::bidirectional_iterator_tag iterator_category; 59 | typedef typename chooseConst::type reference; 60 | typedef typename chooseConst::type pointer; 61 | typedef Node* nodePtr; 62 | 63 | 64 | /* ------------------------------------------------------------- */ 65 | /* ------------------------- ATTRIBUTES ------------------------ */ 66 | 67 | private: 68 | 69 | nodePtr _node; // Pointer to a binary tree's node 70 | nodePtr _lastElem; // Pointer to the dummy node of binary tree 71 | key_compare _comp; // Comparison object used to sort the binary tree 72 | 73 | 74 | /* ------------------------------------------------------------- */ 75 | /* ------------------------ COPLIEN FORM ----------------------- */ 76 | 77 | public: 78 | 79 | /** 80 | * Default constructor, creates a map_iterator pointing to a node. 81 | * 82 | * @param node A pointer to a node containing a T element. Value initialized if not provided. 83 | * @param lastElem A pointer to the dummy node of the binary tree. Value initialized if not provided. 84 | * @param comp The comparison object used to sort the binary tree. Value initialized if not provided. 85 | */ 86 | map_iterator(nodePtr node = 0, nodePtr lastElem = 0, 87 | const key_compare& comp = key_compare()) : 88 | _node(node), _lastElem(lastElem), _comp(comp) {} 89 | 90 | /** 91 | * Copy constructor : creates a const map_iterator pointing to the same node. 92 | * Convert constructor : creates a map_iterator from a const map_iterator, 93 | * pointing to the same node. 94 | * 95 | * @param copy The iterator that will be copied. 96 | */ 97 | map_iterator(const map_iterator& copy) 98 | { 99 | _node = copy.getNode(); 100 | _lastElem = copy.getLastElem(); 101 | _comp = copy.getCompare(); 102 | } 103 | 104 | ~map_iterator() {} 105 | 106 | /** 107 | * Assigns a map_iterator to this map_iterator. Both iterators will point to the 108 | * same node. 109 | * 110 | * @param x The map_iterator that will be assigned. 111 | */ 112 | map_iterator& operator=(const map_iterator& assign) 113 | { 114 | if (this != &assign) 115 | { 116 | _node = assign._node; 117 | _lastElem = assign._lastElem; 118 | _comp = assign._comp; 119 | } 120 | return (*this); 121 | } 122 | 123 | 124 | /* ------------------------------------------------------------- */ 125 | /* -------------------------- GETTERS -------------------------- */ 126 | 127 | /** 128 | * @return A non constant pointer to the actual node that the iterator is 129 | * pointing to. 130 | */ 131 | nodePtr getNode() const { return _node; } 132 | 133 | /** 134 | * @return A non constant pointer to the dummy node at the end of the 135 | * binary tree. 136 | */ 137 | nodePtr getLastElem() const { return _lastElem; } 138 | 139 | /** 140 | * @return The comparison object used to sort the binary tree. 141 | */ 142 | key_compare getCompare() const { return _comp; } 143 | 144 | 145 | /* ------------------------------------------------------------- */ 146 | /* -------------------------- OPERATORS ------------------------ */ 147 | 148 | reference operator*() const { return (_node->content); } 149 | pointer operator->() const { return (&_node->content); } 150 | 151 | /** 152 | * Starts from a specific key inside the tree, and looks for the closest superior key 153 | * key in the tree. 154 | */ 155 | map_iterator& operator++() 156 | { 157 | // To save base value and compare it with parents if no right son 158 | nodePtr previousNode = _node; 159 | 160 | // Special case where iterator is on lastElem : we're looping to the beginning 161 | // of the tree 162 | if (_node == _lastElem) 163 | { 164 | _node = _lastElem->right; 165 | return (*this); 166 | } 167 | 168 | // _comp is equivalent to operator <. So: 169 | // - operator>(lhs, rhs) <==> _comp(rhs, lhs) 170 | // - operator<=(lhs, rhs) <==> !_comp(rhs, lhs) 171 | // - operator>=(lhs, rhs) <==> !_comp(lhs, rhs) 172 | 173 | // Moving node* until we find a node with an higher value or equal value (_lastElem == end) 174 | // <=> _node->content.first <= previousNode->content.first 175 | while (_node != _lastElem && !_comp(previousNode->content.first, _node->content.first)) 176 | { 177 | // Case right son is either node with higher value or _lastElem node 178 | if (_node->right && (_node->right == _lastElem || 179 | _comp(previousNode->content.first, _node->right->content.first))) 180 | // <=> _node->right->content.first > previousNode->content.first 181 | { 182 | _node = _node->right; 183 | 184 | // Starting from the minimum key in the right subtree 185 | Node* tmp = 0; 186 | if (_node != _lastElem && (tmp = searchMinNode(_node))) 187 | _node = tmp; 188 | } 189 | 190 | // No right son so need to go up of one level and try same loop with node's parent 191 | else 192 | _node = _node->parent; 193 | } 194 | return (*this); 195 | } 196 | 197 | /** 198 | * Starts from a specific key inside the tree, and looks for the closest superior key 199 | * key in the tree. 200 | */ 201 | map_iterator operator++(int) 202 | { 203 | // Same logic than in ++operator 204 | map_iterator res(*this); 205 | 206 | if (_node == _lastElem) 207 | { 208 | _node = _lastElem->right; 209 | return (res); 210 | } 211 | 212 | while (_node != _lastElem && !_comp(res->first, _node->content.first)) 213 | { 214 | if (_node->right && (_node->right == _lastElem || 215 | _comp(res->first, _node->right->content.first))) 216 | { 217 | _node = _node->right; 218 | 219 | Node* tmp = 0; 220 | if (_node != _lastElem && (tmp = searchMinNode(_node))) 221 | _node = tmp; 222 | } 223 | else 224 | _node = _node->parent; 225 | } 226 | 227 | return (res); 228 | } 229 | 230 | /** 231 | * Starts from a specific key inside the tree, and looks for the closest inferior key 232 | * key in the tree. 233 | */ 234 | map_iterator& operator--() 235 | { 236 | // Opposite logic than in ++operator 237 | nodePtr previousNode = _node; 238 | 239 | if (_node == _lastElem) 240 | { 241 | _node = _lastElem->left; 242 | return (*this); 243 | } 244 | 245 | while (_node != _lastElem && !_comp(_node->content.first, previousNode->content.first)) 246 | { 247 | if (_node->left && (_node->left == _lastElem || 248 | _comp(_node->left->content.first, previousNode->content.first))) 249 | { 250 | _node = _node->left; 251 | 252 | Node* tmp = 0; 253 | if (_node != _lastElem && (tmp = searchMaxNode(_node))) 254 | _node = tmp; 255 | } 256 | else 257 | _node = _node->parent; 258 | } 259 | 260 | return (*this); 261 | } 262 | 263 | /** 264 | * Starts from a specific key inside the tree, and looks for the closest inferior key 265 | * key in the tree. 266 | */ 267 | map_iterator operator--(int) 268 | { 269 | // Opposite logic than in ++operator 270 | map_iterator res(*this); 271 | 272 | if (_node == _lastElem) 273 | { 274 | _node = _lastElem->left; 275 | return (res); 276 | } 277 | 278 | while (_node != _lastElem && !_comp(_node->content.first, res->first)) 279 | { 280 | if (_node->left && (_node->left == _lastElem || 281 | _comp(_node->left->content.first, res->first))) 282 | { 283 | _node = _node->left; 284 | 285 | Node* tmp = 0; 286 | if (_node != _lastElem && (tmp = searchMaxNode(_node))) 287 | _node = tmp; 288 | } 289 | else 290 | _node = _node->parent; 291 | } 292 | 293 | return (res); 294 | } 295 | 296 | bool operator==(const map_iterator& it) const { return (it._node == _node); } 297 | bool operator!=(const map_iterator& it) const { return (it._node != _node); } 298 | 299 | 300 | /* ----------------- PRIVATE MEMBER FUNCTIONS ------------------ */ 301 | /* ------------------------------------------------------------- */ 302 | 303 | private: 304 | 305 | /** 306 | * Searches for the element with the highest key in the tree. 307 | * 308 | * @param root First node of the tree. 309 | * @param return The element containing the highest key in the tree. 310 | */ 311 | Node* searchMaxNode(Node *root) 312 | { 313 | // Until we meet tree's right extremity and circular link _lastElem 314 | if (root && root != _lastElem && root->right && root->right != _lastElem) 315 | return searchMaxNode(root->right); 316 | return root; 317 | } 318 | 319 | /** 320 | * Searches for the element with the lowest key in the tree. 321 | * 322 | * @param root First node of the tree. 323 | * @param return The element containing the lowest key in the tree. 324 | */ 325 | Node* searchMinNode(Node *root) 326 | { 327 | // Until we meet tree's left extremity and circular link _lastElem 328 | if (root && root != _lastElem && root->left && root->left != _lastElem) 329 | return searchMinNode(root->left); 330 | return root; 331 | } 332 | 333 | }; // class map_iterator 334 | 335 | } // namespace ft 336 | 337 | 338 | #endif -------------------------------------------------------------------------------- /iterators/rev_map_iterator.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* rev_map_iterator.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: llefranc +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2021/01/07 15:06:15 by llefranc #+# #+# */ 9 | /* Updated: 2021/02/15 10:49:09 by llefranc ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | #ifndef REV_MAP_ITERATOR_HPP 14 | #define REV_MAP_ITERATOR_HPP 15 | 16 | #include "../templates/type1_or_type2.hpp" 17 | #include "map_iterator.hpp" 18 | 19 | namespace ft 20 | { 21 | /** 22 | * ------------------------------------------------------------- * 23 | * -------------------- FT::REV_MAP_ITERATOR ------------------- * 24 | * 25 | * - Coplien form: 26 | * (constructor): Construct rev_map_iterator 27 | * (destructor): Rev_map_iterator destructor 28 | * operator=: Assign content 29 | * 30 | * - Operators 31 | * operators: Operators for rev_map_iterator 32 | * non-member operators: Operators for rev_map_iterator 33 | * ------------------------------------------------------------- * 34 | */ 35 | 36 | /** 37 | * @param Key Type of container's key elements. 38 | * @param T Type of container's mapped elements. 39 | * @param Compare The predicate used to sort the binary tree. 40 | * @param Node The structure used as nodes in the binary tree. 41 | * @param B Boolean to indicate if it's an iterator / a const iterator. 42 | */ 43 | template 44 | class rev_map_iterator 45 | { 46 | /* ------------------------------------------------------------- */ 47 | /* -------------------------- ALIASES -------------------------- */ 48 | 49 | public: 50 | 51 | typedef Key key_type; 52 | typedef Compare key_compare; 53 | typedef T mapped_type; 54 | 55 | typedef ft::pair value_type; 56 | typedef long int difference_type; 57 | typedef size_t size_type; 58 | 59 | typedef std::bidirectional_iterator_tag iterator_category; 60 | typedef typename chooseConst::type reference; 61 | typedef typename chooseConst::type pointer; 62 | typedef Node* nodePtr; 63 | 64 | 65 | /* ------------------------------------------------------------- */ 66 | /* ------------------------- ATTRIBUTES ------------------------ */ 67 | 68 | private: 69 | 70 | nodePtr _node; // Pointer to a binary tree's node 71 | nodePtr _lastElem; // Pointer to the dummy node of binary tree 72 | key_compare _comp; // Comparison object used to sort the binary tree 73 | 74 | 75 | /* ------------------------------------------------------------- */ 76 | /* ------------------------ COPLIEN FORM ----------------------- */ 77 | 78 | public: 79 | 80 | /** 81 | * Default constructor, creates a rev_map_iterator pointing to a node. 82 | * 83 | * @param node A pointer to a node containing a T element. Value initialized if not provided. 84 | * @param lastElem A pointer to the dummy node of the binary tree. Value initialized if not provided. 85 | * @param comp The comparison object used to sort the binary tree. Value initialized if not provided. 86 | */ 87 | rev_map_iterator(nodePtr node = 0, nodePtr lastElem = 0, 88 | const key_compare& comp = key_compare()) : 89 | _node(node), _lastElem(lastElem), _comp(comp) {} 90 | 91 | /** 92 | * Copy constructor : creates a const rev_map_iterator pointing to the same node. 93 | * Convert constructor : creates a rev_map_iterator from a const rev_map_iterator, 94 | * pointing to the same node. 95 | * 96 | * @param copy The iterator that will be copied. 97 | */ 98 | rev_map_iterator(const rev_map_iterator& copy) 99 | { 100 | _node = copy.getNonConstNode(); 101 | _lastElem = copy.getNonConstLastElem(); 102 | _comp = copy.getCompare(); 103 | } 104 | 105 | /** 106 | * Convert constructor : creates a rev_map_iterator from a const / not const 107 | * map_iterator, pointing to the previous T element. This is necessary so 108 | * begin() == rend(), and end == rbegin(). 109 | * 110 | * @param copy The map_iterator that will be converted. 111 | */ 112 | explicit rev_map_iterator(map_iterator copy) 113 | { 114 | --copy; 115 | _node = copy.getNonConstNode(); 116 | _lastElem = copy.getNonConstLastElem(); 117 | _comp = copy.getCompare(); 118 | } 119 | 120 | ~rev_map_iterator() {} 121 | 122 | /** 123 | * Assigns a rev_map_iterator to this rev_map_iterator. Both iterators will point to the 124 | * same node. 125 | * 126 | * @param x The rev_map_iterator that will be assigned. 127 | */ 128 | rev_map_iterator& operator=(const rev_map_iterator& assign) 129 | { 130 | if (this != &assign) 131 | { 132 | _node = assign._node; 133 | _lastElem = assign._lastElem; 134 | _comp = assign._comp; 135 | } 136 | return (*this); 137 | } 138 | 139 | 140 | /* ------------------------------------------------------------- */ 141 | /* --------------------------- GETTERS ------------------------- */ 142 | 143 | /** 144 | * @return A non constant pointer to the actual node that the iterator is 145 | * pointing to. 146 | */ 147 | nodePtr getNonConstNode() const { return _node; } 148 | 149 | /** 150 | * @return A non constant pointer to the dummy node at the end of the 151 | * binary tree. 152 | */ 153 | nodePtr getNonConstLastElem() const { return _lastElem; } 154 | 155 | /** 156 | * @return The comparison object used to sort the binary tree. 157 | */ 158 | key_compare getCompare() const { return _comp; } 159 | 160 | 161 | /* ------------------------------------------------------------- */ 162 | /* -------------------------- OPERATORS ------------------------ */ 163 | 164 | reference operator*() const { return (_node->content); } 165 | pointer operator->() const { return (&_node->content); } 166 | 167 | /** 168 | * Starts from a specific key inside the tree, and looks for the closest inferior key 169 | * key in the tree. 170 | */ 171 | rev_map_iterator& operator++() 172 | { 173 | // Opposite logic than in --operator 174 | nodePtr previousNode = _node; 175 | 176 | if (_node == _lastElem) 177 | { 178 | _node = _lastElem->left; 179 | return (*this); 180 | } 181 | 182 | while (_node != _lastElem && !_comp(_node->content.first, previousNode->content.first)) 183 | { 184 | if (_node->left && (_node->left == _lastElem || 185 | _comp(_node->left->content.first, previousNode->content.first))) 186 | { 187 | _node = _node->left; 188 | 189 | Node* tmp = 0; 190 | if (_node != _lastElem && (tmp = searchMaxNode(_node))) 191 | _node = tmp; 192 | } 193 | else 194 | _node = _node->parent; 195 | } 196 | 197 | return (*this); 198 | } 199 | 200 | /** 201 | * Starts from a specific key inside the tree, and looks for the closest inferior key 202 | * key in the tree. 203 | */ 204 | rev_map_iterator operator++(int) 205 | { 206 | // Opposite logic than in --operator 207 | rev_map_iterator res(*this); 208 | 209 | if (_node == _lastElem) 210 | { 211 | _node = _lastElem->left; 212 | return (res); 213 | } 214 | 215 | while (_node != _lastElem && !_comp(_node->content.first, res->first)) 216 | { 217 | if (_node->left && (_node->left == _lastElem || 218 | _comp(_node->left->content.first, res->first))) 219 | { 220 | _node = _node->left; 221 | 222 | Node* tmp = 0; 223 | if (_node != _lastElem && (tmp = searchMaxNode(_node))) 224 | _node = tmp; 225 | } 226 | else 227 | _node = _node->parent; 228 | } 229 | 230 | return (res); 231 | } 232 | 233 | /** 234 | * Starts from a specific key inside the tree, and looks for the closest superior key 235 | * key in the tree. 236 | */ 237 | rev_map_iterator& operator--() 238 | { 239 | // To save base value and compare it with parents if no right son 240 | nodePtr previousNode = _node; 241 | 242 | // Special case where iterator is on lastElem : we're looping to the beginning 243 | // of the tree 244 | if (_node == _lastElem) 245 | { 246 | _node = _lastElem->right; 247 | return (*this); 248 | } 249 | 250 | // _comp is equivalent to operator <. So: 251 | // - operator>(lhs, rhs) <==> _comp(rhs, lhs) 252 | // - operator<=(lhs, rhs) <==> !_comp(rhs, lhs) 253 | // - operator>=(lhs, rhs) <==> !_comp(lhs, rhs) 254 | 255 | // Moving node* until we find a node with an higher value or equal value (_lastElem == end) 256 | // <=> _node->content.first <= previousNode->content.first) 257 | while (_node != _lastElem && !_comp(previousNode->content.first, _node->content.first)) 258 | { 259 | // Case right son is either node with higher value or _lastElem node 260 | if (_node->right && (_node->right == _lastElem || 261 | // <=> _node->right->content.first > previousNode->content.first)) 262 | _comp(previousNode->content.first, _node->right->content.first))) 263 | { 264 | _node = _node->right; 265 | 266 | // Starting from the minimum key in the right subtree 267 | Node* tmp = 0; 268 | if (_node != _lastElem && (tmp = searchMinNode(_node))) 269 | _node = tmp; 270 | } 271 | 272 | // No right son so need to go up of one level and try same loop with node's parent 273 | else 274 | _node = _node->parent; 275 | } 276 | return (*this); 277 | } 278 | 279 | /** 280 | * Starts from a specific key inside the tree, and looks for the closest superior key 281 | * key in the tree. 282 | */ 283 | rev_map_iterator operator--(int) 284 | { 285 | // Same logic than in ++operator 286 | rev_map_iterator res(*this); 287 | 288 | if (_node == _lastElem) 289 | { 290 | _node = _lastElem->right; 291 | return (res); 292 | } 293 | 294 | while (_node != _lastElem && !_comp(res->first, _node->content.first)) 295 | { 296 | if (_node->right && (_node->right == _lastElem || 297 | _comp(res->first, _node->right->content.first))) 298 | { 299 | _node = _node->right; 300 | 301 | Node* tmp = 0; 302 | if (_node != _lastElem && (tmp = searchMinNode(_node))) 303 | _node = tmp; 304 | } 305 | else 306 | _node = _node->parent; 307 | } 308 | 309 | return (res); 310 | } 311 | 312 | bool operator==(const rev_map_iterator& it) const { return (it._node == _node); } 313 | bool operator!=(const rev_map_iterator& it) const { return (it._node != _node); } 314 | 315 | 316 | /* ----------------- PRIVATE MEMBER FUNCTIONS ------------------ */ 317 | /* ------------------------------------------------------------- */ 318 | 319 | private: 320 | 321 | /** 322 | * Searches for the element with the highest key in the tree. 323 | * 324 | * @param root First node of the tree. 325 | * @param return The element containing the highest key in the tree. 326 | */ 327 | Node* searchMaxNode(Node *root) 328 | { 329 | // Until we meet tree's right extremity and circular link _lastElem 330 | if (root && root != _lastElem && root->right && root->right != _lastElem) 331 | return searchMaxNode(root->right); 332 | return root; 333 | } 334 | 335 | /** 336 | * Searches for the element with the lowest key in the tree. 337 | * 338 | * @param root First node of the tree. 339 | * @param return The element containing the lowest key in the tree. 340 | */ 341 | Node* searchMinNode(Node *root) 342 | { 343 | // Until we meet tree's left extremity and circular link _lastElem 344 | if (root && root != _lastElem && root->left && root->left != _lastElem) 345 | return searchMinNode(root->left); 346 | return root; 347 | } 348 | 349 | }; // class rev_map_iterator 350 | 351 | } // namespace ft 352 | 353 | #endif -------------------------------------------------------------------------------- /containers/vector.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* vector.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq 17 | #include 18 | #include 19 | 20 | #include "../iterators/vector_iterator.hpp" 21 | #include "../iterators/rev_vector_iterator.hpp" 22 | #include "../templates/stl_like.hpp" 23 | 24 | #include 25 | 26 | namespace ft 27 | { 28 | /** 29 | * ------------------------------------------------------------- * 30 | * ------------------------ FT::VECTOR ------------------------- * 31 | * 32 | * - Coplien form: 33 | * (constructor): Construct vector 34 | * (destructor): Destruct vector 35 | * operator=: Assign vector 36 | * 37 | * - Iterators: 38 | * begin: Return iterator to beginning 39 | * end: Return iterator to end 40 | * rbegin: Return reverse iterator to reverse beginning 41 | * rend: Return reverse iterator to reverse end 42 | * 43 | * - Capacity: 44 | * size: Return size 45 | * max_size: Return maximum size 46 | * resize: Change size 47 | * capacity: Return size of allocated storage capacity 48 | * empty: Test whether vector is empty 49 | * reserve: Request a change in capacity 50 | * 51 | * - Element access: 52 | * operator[]: Access element 53 | * at: Access element 54 | * front: Access first element 55 | * back: Access last element 56 | * 57 | * - Modifiers: 58 | * assign: Assign vector content 59 | * push_back: Add element at the end 60 | * pop_back: Delete last element 61 | * insert: Insert elements 62 | * erase: Erase elements 63 | * swap: Swap content 64 | * clear: Clear content 65 | * 66 | * - Non-member function overloads: 67 | * relational operators: Relational operators for vector 68 | * swap: Exchange contents of two vectors 69 | * ------------------------------------------------------------- * 70 | */ 71 | 72 | /** 73 | * @param T Type of container's elements. 74 | * @param Alloc Object used to manage the vector' storage. 75 | */ 76 | template > 77 | class vector 78 | { 79 | public: 80 | 81 | /* ------------------------------------------------------------- */ 82 | /* -------------------------- ALIASES -------------------------- */ 83 | 84 | typedef T value_type; 85 | typedef Alloc allocator_type; 86 | typedef long int difference_type; 87 | typedef size_t size_type; 88 | 89 | typedef T& reference; 90 | typedef const T& const_reference; 91 | typedef T* pointer; 92 | typedef const T* const_pointer; 93 | 94 | typedef typename ft::vector_iterator iterator; 95 | typedef typename ft::vector_iterator const_iterator; 96 | 97 | typedef typename ft::rev_vector_iterator reverse_iterator; 98 | typedef typename ft::rev_vector_iterator const_reverse_iterator; 99 | 100 | 101 | /* ------------------------------------------------------------- */ 102 | /* ------------------------- ATTRIBUTES ------------------------ */ 103 | 104 | private: 105 | 106 | Alloc _alloc; // Copy of allocator_type object 107 | pointer _vector; // Pointer on an array of T values 108 | size_type _size; // Number of T values inside the vector 109 | size_type _capacity; // Capacity allocated (can be greater than size) 110 | 111 | 112 | /* ------------------------------------------------------------- */ 113 | /* ------------------------ COPLIEN FORM ----------------------- */ 114 | 115 | public: 116 | 117 | /** 118 | * Default constructor, creates a vector with a size of 0. 119 | * 120 | * @param alloc The template param used for the allocation. 121 | */ 122 | explicit vector(const allocator_type& alloc = allocator_type()) : 123 | _alloc(alloc), _size(0), _capacity(0) 124 | { 125 | _vector = _alloc.allocate(_capacity); 126 | }; 127 | 128 | /** 129 | * Fill constructor, creates a vector with a size of n and initializes the 130 | * values. 131 | * 132 | * @param n The number of elements that will be created. 133 | * @param val The value used for initialization (value initialized by default). 134 | * @param alloc The template param used for the allocation. 135 | */ 136 | explicit vector(size_type n, const value_type& val = value_type(), 137 | const allocator_type& alloc = allocator_type()) : 138 | _alloc(alloc), _size(n), _capacity(n) 139 | { 140 | _vector = _alloc.allocate(_capacity); 141 | 142 | for (size_type i = 0; i < _size; ++i) 143 | _alloc.construct(&_vector[i], val); 144 | } 145 | 146 | /** 147 | * Range constructor, creates a vector with a size equal to the range between two 148 | * iterators and copy the values of this range to the new elements created. 149 | * 150 | * @param first An iterator representing first element of the range. 151 | * @param last An iterator indicating end of the range (will be excluded and not copied). 152 | * @param alloc The template param used for the allocation. 153 | */ 154 | template 155 | vector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type(), 156 | typename ft::enable_if::value >::type* = 0) : 157 | _alloc(alloc), _size(0) 158 | { 159 | InputIterator tmp(first); 160 | while (tmp++ != last) 161 | _size++; 162 | 163 | _capacity = _size; 164 | _vector = _alloc.allocate(_capacity); 165 | 166 | for (int i = 0; first != last; ++first, ++i) 167 | _alloc.construct(&_vector[i], *first); 168 | } 169 | 170 | /** 171 | * Copy constructor, creates a vector with the same size and copy/construct 172 | * all x values to the new area allocated. 173 | * 174 | * @param x The vector that will be copied. 175 | */ 176 | vector(const vector& x) : 177 | _alloc(x._alloc), _size(x._size), _capacity(x._capacity) 178 | { 179 | _vector = _alloc.allocate(_capacity); 180 | 181 | for (ft::pair i(0, x.begin()); 182 | i.second != x.end(); ++i.first, ++i.second) 183 | _alloc.construct(&_vector[i.first], *i.second); 184 | } 185 | 186 | /** 187 | * Destructor, destroys all the vector's elements and then deallocates vector's 188 | * ressources. 189 | */ 190 | ~vector() 191 | { 192 | for (iterator it = begin(); it != end(); ++it) 193 | _alloc.destroy(&(*it)); 194 | _alloc.deallocate(_vector, _capacity); 195 | } 196 | 197 | /** 198 | * Assigns a vector to this vector. Calls the copy constructor to do the 199 | * assignment(copy and swap idiom). 200 | * 201 | * @param x The vector that will be assigned. 202 | */ 203 | vector& operator= (const vector& x) 204 | { 205 | vector tmp(x); 206 | swap(tmp); 207 | return *this; 208 | } 209 | 210 | 211 | /* ------------------------------------------------------------- */ 212 | /* ------------------------- ITERATORS ------------------------- */ 213 | 214 | /** 215 | * @return An iterator pointing to the first element of the vector. 216 | */ 217 | iterator begin() { return iterator(_vector); } 218 | 219 | /** 220 | * @return A const_iterator pointing to the first element of the vector. 221 | */ 222 | const_iterator begin() const { return const_iterator(_vector); } 223 | 224 | /** 225 | * @return An iterator pointing after the last element of the vector. Access this 226 | * iterator will result in undefined behavior. 227 | */ 228 | iterator end() { return iterator(_vector + _size); } 229 | 230 | /** 231 | * @return A const_iterator pointing after the last element of the vector. Access this 232 | * iterator will result in undefined behavior. 233 | */ 234 | const_iterator end() const { return const_iterator(_vector + _size); } 235 | 236 | /** 237 | * @return A reverse_iterator pointing to the last element of the vector. 238 | */ 239 | reverse_iterator rbegin() { return reverse_iterator(_vector + _size - 1); } 240 | 241 | /** 242 | * @return A const_reverse_iterator pointing to the last element of the vector. 243 | */ 244 | const_reverse_iterator rbegin() const { return const_reverse_iterator(_vector + _size - 1); } 245 | 246 | /** 247 | * @return A reverse_iterator pointing before the first element of the vector. Access this 248 | * iterator will result in undefined behavior. 249 | */ 250 | reverse_iterator rend() { return reverse_iterator(_vector - 1); } 251 | 252 | /** 253 | * @return A const_reverse_iterator pointing before the first element of the vector. Access 254 | * this iterator will result in undefined behavior. 255 | */ 256 | const_reverse_iterator rend() const { return const_reverse_iterator(_vector - 1); } 257 | 258 | 259 | /* ------------------------------------------------------------- */ 260 | /* -------------------------- CAPACITY ------------------------- */ 261 | 262 | /** 263 | * @return The size of the vector. 264 | */ 265 | size_type size() const { return _size; } 266 | 267 | /** 268 | * @return The max possible size to be allocated. 269 | */ 270 | size_type max_size() const 271 | { 272 | if (sizeof(value_type) == 1) 273 | return static_cast(pow(2.0, 64.0) / 2.0) - 1; 274 | return static_cast(pow(2.0, 64.0) / static_cast(sizeof(value_type))) - 1; 275 | } 276 | 277 | /** 278 | * Resizes the vector so that it contains n elements. If the capacity isn't 279 | * enough, a reallocation will happen. 280 | * 281 | * @param n The number of elements that the vector will contain after beeing resized. 282 | * @param val If new elements need to be added, they will be initialize with val 283 | * (value initialize by default). 284 | */ 285 | void resize (size_type n, value_type val = value_type()) 286 | { 287 | if (n > _capacity) 288 | reallocateVec(n); 289 | while (n > _size) 290 | push_back(val); 291 | while (n < _size) 292 | pop_back(); 293 | } 294 | 295 | /** 296 | * @return The actual size of the capacity allocated (in number of possible elements 297 | * than the vector can contain). 298 | */ 299 | size_type capacity() const { return _capacity; } 300 | 301 | /** 302 | * @return True if the vector' size is equal to 0. 303 | */ 304 | bool empty() const { return _size == 0; } 305 | 306 | /** 307 | * Requests that the vector capacity be at least enough to contain n elements. If the 308 | * actual capacity is greater than n, nothing happen. If the capacity requested 309 | * is > than max size, a lenght_error exception is thrown. 310 | * 311 | * @param n The new capacity to be allocated. 312 | */ 313 | void reserve (size_type n) 314 | { 315 | if (n > max_size()) 316 | throw std::length_error("vector"); 317 | if (n > _capacity) 318 | reallocateVec(n); 319 | } 320 | 321 | 322 | /* ------------------------------------------------------------- */ 323 | /* ---------------------- ELEMENTS ACCESS ---------------------- */ 324 | 325 | /** 326 | * Access an element at n index. Undefined behavior if n is outside 327 | * vector's range. 328 | * 329 | * @return A reference to the element at n index. 330 | */ 331 | reference operator[] (size_type n) { return _vector[n]; } 332 | 333 | /** 334 | * Access an element at n index. Undefined behavior if n is outside 335 | * vector's range. 336 | * 337 | * @return A const reference to the element at n index. 338 | */ 339 | const_reference operator[] (size_type n) const { return _vector[n]; } 340 | 341 | /** 342 | * Access an element at n index. If n is outside vector's range, throw an 343 | * out_of_range exception. 344 | * 345 | * @return A reference to the element at n index. 346 | */ 347 | reference at(size_type n) 348 | { 349 | if (!(n < _size)) 350 | throw std::out_of_range("vector"); 351 | return _vector[n]; 352 | } 353 | 354 | /** 355 | * Access an element at n index. If n is outside vector's range, throw an 356 | * out_of_range exception. 357 | * 358 | * @return A const reference to the element at n index. 359 | */ 360 | const_reference at(size_type n) const 361 | { 362 | if (!(n < _size)) 363 | throw std::out_of_range("vector"); 364 | return _vector[n]; 365 | } 366 | 367 | /** 368 | * Access first vector's element. Undefined behavior if the vector is empty. 369 | * 370 | * @return A reference to the first vector's element. 371 | */ 372 | reference front() { return _vector[0]; } 373 | 374 | /** 375 | * Access first vector's element. Undefined behavior if the vector is empty. 376 | * 377 | * @return A const reference to the first vector's element. 378 | */ 379 | const_reference front() const { return _vector[0]; } 380 | 381 | /** 382 | * Access last vector's element. Undefined behavior if the vector is empty. 383 | * 384 | * @return A reference to the last vector's element. 385 | */ 386 | reference back() { return _vector[_size - 1]; } 387 | 388 | /** 389 | * Access last vector's element. Undefined behavior if the vector is empty. 390 | * 391 | * @return A const reference to the last vector's element. 392 | */ 393 | const_reference back() const { return _vector[_size - 1]; } 394 | 395 | 396 | /* ------------------------------------------------------------- */ 397 | /* ------------------------- MODIFIERS ------------------------- */ 398 | 399 | /** 400 | * Assigns new contents to the vector, replacing its current content, 401 | * and modifying its size accordingly. The new contents are elements constructed 402 | * from each of the elements in the range between first and last iterators. 403 | * 404 | * @param first An iterator pointing at the beginning of the range (will be included). 405 | * @param last An iterator pointing at the end of the range (will not be included) 406 | */ 407 | template 408 | void assign (InputIterator first, InputIterator last, 409 | typename ft::enable_if::value >::type* = 0) 410 | { 411 | clear(); 412 | 413 | // Reallocating only if new capacity exceeds previous 414 | size_type n = static_cast(last - first); 415 | if (n > _capacity) 416 | { 417 | _alloc.deallocate(_vector, _capacity); 418 | _vector = _alloc.allocate(n); 419 | } 420 | 421 | size_type i = 0; 422 | for (; first != last; ++i, ++first) 423 | _alloc.construct(&_vector[i], *first); 424 | _size = i; 425 | } 426 | 427 | /** 428 | * Assigns new contents to the vector, replacing its current content, 429 | * and modifying its size accordingly. 430 | * 431 | * @param n Number of new elements constructed. 432 | * @param val Each new elements will be copy constructed from val. 433 | */ 434 | void assign (size_type n, const value_type& val) 435 | { 436 | clear(); 437 | 438 | // Reallocating only if new capacity exceeds previous 439 | if (n > _capacity) 440 | { 441 | _alloc.deallocate(_vector, _capacity); 442 | _vector = _alloc.allocate(n); 443 | } 444 | 445 | for (size_type i = 0; i < n; ++i) 446 | _alloc.construct(&_vector[i], val); 447 | _size = n; 448 | } 449 | 450 | 451 | /** 452 | * Adds a new element at the end of the vector, after its current last element. 453 | * Size is increased and a reallocation happen if actual capacity isn't enough. 454 | * 455 | * @param val The new element will be copy constructed from val. 456 | */ 457 | void push_back (const value_type& val) 458 | { 459 | if (_size + 1 > _capacity) 460 | reallocateVec(!_capacity ? 1 : _capacity * 2); 461 | _alloc.construct(&_vector[_size++], val); 462 | } 463 | 464 | /** 465 | * Removes the last element in the vector, reducing the container size by one. 466 | * This destroys the removed element. Does nothing if the vector is empty. 467 | */ 468 | void pop_back() 469 | { 470 | if (_size) 471 | _alloc.destroy(&_vector[_size-- - 1]); 472 | } 473 | 474 | /** 475 | * Inserts 1 element with a value of val at a position, and increases the vector' size. 476 | * A reallocation will occured only if vector's capacity isn't enough. 477 | * 478 | * @param position The element will be inserted just before this position. All elements 479 | * after this position will be moved of a len of 1. 480 | * @param val Value of the element inserted. 481 | * @return An iterator on the newly element inserted. 482 | */ 483 | iterator insert (iterator position, const value_type& val) 484 | { 485 | // In case of a realloc, position will be invalited because _vector 486 | // points to another allocated area so we need to save the index array 487 | // where position iterator is pointing to create a new one after the reallocation 488 | difference_type index = position - begin(); 489 | 490 | insert(position, 1, val); 491 | return iterator(&_vector[index]); 492 | } 493 | 494 | /** 495 | * Inserts n elements with a value of val at a position, and increases the vector' size. 496 | * A reallocation will occured only if vector's capacity isn't enough. 497 | * 498 | * @param position Elements will be inserted just before this position. All elements 499 | * after this position will be moved of a len of n. 500 | * @param n Number of elements to be inserted. 501 | * @param val Value of the elements inserted. 502 | */ 503 | void insert (iterator position, size_type n, const value_type& val) 504 | { 505 | // In case of a realloc, position will be invalited because _vector 506 | // points to another allocated area so we need to save the index array 507 | // where position iterator is pointing to create a new one after the reallocation 508 | difference_type index = position - begin(); 509 | 510 | if (_size + n > _capacity) 511 | reallocateVec(_capacity + n); 512 | 513 | // Creating a new iterator pointing to the correct allocated are (case a realloc occured previously) 514 | iterator newPosition(&_vector[index]); 515 | 516 | // Moving at newPosition + n all elements after newPosition 517 | if (newPosition != end()) 518 | moveElementsToTheRight(newPosition, n); 519 | 520 | // Constructing n new elements from val 521 | for (size_type i = 0; i < n; ++i) 522 | _alloc.construct(&(*newPosition++), val); 523 | _size += n; 524 | } 525 | 526 | /** 527 | * Inserts all elements between first and last, and increases the vector' size. 528 | * A reallocation will occured only if vector's capacity isn't enough. 529 | * 530 | * @param position Elements will be inserted just before this position. All elements 531 | * after this position will be moved of the range' size. 532 | * @param first An iterator pointing to the range's beginning (will be include). 533 | * @param last An iterator pointing to the range's end (will not be include). 534 | */ 535 | template 536 | void insert (iterator position, InputIterator first, InputIterator last, 537 | typename ft::enable_if::value >::type* = 0) 538 | { 539 | // Counting number of elements to add 540 | size_type n = 0; 541 | InputIterator tmp(first); 542 | while (tmp++ != last) 543 | ++n; 544 | 545 | // In case of a realloc, position will be invalited because _vector 546 | // points to another allocated area so we need to save the index array 547 | // where position iterator is pointing to create a new one after the reallocation 548 | difference_type index = position - begin(); 549 | 550 | if (_size + n > _capacity) 551 | reallocateVec(_capacity + n); 552 | 553 | // Creating a new iterator pointing to the correct allocated are (case a realloc occured previously) 554 | iterator newPosition(&_vector[index]); 555 | 556 | // Moving at newPosition + n all elements after newPosition 557 | if (newPosition != end()) 558 | moveElementsToTheRight(newPosition, n); 559 | 560 | // Constructing n new elements from the iterator's range 561 | for (size_type i = 0; i < n; ++i) 562 | _alloc.construct(&(*newPosition++), *first++); 563 | _size += n; 564 | } 565 | 566 | /** 567 | * Removes from the vector a single element and reduces vector' size by 1. 568 | * Erasing elements other than vector.end() will occured a reallocation. 569 | * 570 | * @param position The element that will erased. The element's range past this position 571 | * will be moved to this position. 572 | * @return An iterator pointing to the new location of the element that follows 573 | the element erased by the function call. 574 | */ 575 | iterator erase (iterator position) 576 | { 577 | return erase(position, position + 1); 578 | } 579 | 580 | /** 581 | * Removes from the vector all elements between first and last, and reduces vector' size. 582 | * Erasing elements other than from vector.end() to vector.end() will occured a reallocation. 583 | * 584 | * @param first The beginning of the range to erase (will be include). 585 | * @param last The end of the range to erase (will not be include). The element's range 586 | * past this position will be moved to this first position. 587 | * @return An iterator pointing to the new location of the element that follows 588 | * the elements' range erased by the function call. 589 | */ 590 | iterator erase (iterator first, iterator last) 591 | { 592 | if (first == end() || first == last) 593 | return first; 594 | 595 | // In case of a realloc, iterators will be invalited because _vector 596 | // points to another allocated area so we need to save the index array 597 | // where first is pointing to create a new iterator after the reallocation 598 | difference_type index = first - begin(); 599 | 600 | // If there is elements after the iterators range, we need to move them at first position 601 | if (last < end()) 602 | { 603 | moveElementsToTheLeft(first, last); 604 | _size -= static_cast(last - first); 605 | } 606 | else 607 | { 608 | size_type newSize = _size - static_cast(last - first); 609 | while (_size != newSize) 610 | pop_back(); 611 | } 612 | 613 | return iterator(&_vector[index]); 614 | } 615 | 616 | /** 617 | * Swaps a vector with the content of this one. 618 | * 619 | * @param x The vector to be swapped. 620 | */ 621 | void swap (vector& x) 622 | { 623 | swap(_alloc, x._alloc); 624 | swap(_vector, x._vector); 625 | swap(_size, x._size); 626 | swap(_capacity, x._capacity); 627 | } 628 | 629 | /** 630 | * Removes all elements from the vector (which are destroyed), leaving the 631 | * container with a size of 0. 632 | */ 633 | void clear() 634 | { 635 | while (_size) 636 | pop_back(); 637 | } 638 | 639 | 640 | /* ------------------------------------------------------------- */ 641 | /* --------------- NON-MEMBER FUNCTION OVERLOADS --------------- */ 642 | 643 | /** 644 | * @return True if the 2 vectors have same size and same content. 645 | */ 646 | friend bool operator==(const vector& lhs, const vector& rhs) 647 | { 648 | if (lhs.size() != rhs.size()) 649 | return false; 650 | 651 | for (ft::pair it(lhs.begin(), rhs.begin()); 652 | it.first != lhs.end(); ++it.first, ++it.second) 653 | if (*(it.first) != *(it.second)) 654 | return false; 655 | return true; 656 | } 657 | 658 | /** 659 | * @return True if the 2 vectors have different size or different content. 660 | */ 661 | friend bool operator!=(const vector& lhs, const vector& rhs) { return !(lhs == rhs); } 662 | 663 | /** 664 | * Compares the elements sequentially using operator< and stopping at the 665 | * first occurrence. 666 | * 667 | * @return True if all lhs' elements are < to rhs' elements, or if 668 | * lhs' content == rhs' content and lhs' size < rhs' size. 669 | */ 670 | friend bool operator<(const vector& lhs, const vector& rhs) 671 | { 672 | for (ft::pair it(lhs.begin(), rhs.begin()); 673 | it.first != lhs.end() && it.second != rhs.end(); ++it.first, ++it.second) 674 | if (*(it.first) < *(it.second)) 675 | return true; 676 | return (lhs.size() < rhs.size()); 677 | } 678 | 679 | /** 680 | * Uses operator< to compare the 2 vectors (rhs < lhs). 681 | * 682 | * @return True if all lhs' elements are > to all rhs' elements, or if 683 | * lhs' content == rhs' content and lhs' size > rhs' size. 684 | */ 685 | friend bool operator>(const vector& lhs, const vector& rhs) { return rhs < lhs; } 686 | 687 | /** 688 | * Uses operator< to compare the 2 vectors !(rhs < lhs). 689 | * 690 | * @return True if all lhs' elements are <= to all rhs' elements, or if 691 | * lhs' content == rhs' content and lhs' size <= rhs' size. 692 | */ 693 | friend bool operator<=(const vector& lhs, const vector& rhs) { return !(rhs < lhs); } 694 | 695 | /** 696 | * Uses operator< to compare the 2 vectors !(lhs < rhs). 697 | * 698 | * @return True if all lhs' elements are >= to all rhs' elements, or if 699 | * lhs' content == rhs' content and lhs' size >= rhs' size. 700 | */ 701 | friend bool operator>=(const vector& lhs, const vector& rhs) { return !(lhs < rhs); } 702 | 703 | /** 704 | * Swaps the content of two vectors. 705 | * 706 | * @param x Will be swap with y. 707 | * @param y Will be swap with x. 708 | */ 709 | friend void swap (vector& x, vector& y) { x.swap(y); } 710 | 711 | 712 | /* ------------------------------------------------------------- */ 713 | /* ------------------ PRIVATE MEMBER FUNCTIONS ----------------- */ 714 | 715 | private: 716 | 717 | /** 718 | * Reallocates a vector with a new capacity, and copy/construct the previous 719 | * one using the allocator. Then call destruct the previous one with the destructor. 720 | * 721 | * @param newCapacity The new that will be allocated by the allocator. 722 | */ 723 | void reallocateVec(size_type newCapacity) 724 | { 725 | pointer tmp = _alloc.allocate(newCapacity); 726 | for (size_type i = 0; i < _size; ++i) 727 | _alloc.construct(&tmp[i], _vector[i]); 728 | 729 | this->~vector(); 730 | _capacity = newCapacity; 731 | _vector = tmp; 732 | } 733 | 734 | /** 735 | * Swaps two variables. 736 | * 737 | * @param a Will be swap with b. 738 | * @param b Will be swap with a. 739 | */ 740 | template 741 | void swap(U& a, U&b) 742 | { 743 | U tmp = a; 744 | a = b; 745 | b = tmp; 746 | } 747 | 748 | /** 749 | * Move to the right all elements from a certain position until the end 750 | * of the array. Each element will be constructed/copied to his new position, 751 | * then destructed at his previous position. 752 | * 753 | * @param pos Indicates first element to move. All elements at his right will be moved too. 754 | * @param lenMov The len of the movement for each element. 755 | */ 756 | void moveElementsToTheRight(iterator pos, size_type lenMov) 757 | { 758 | // Starting from the end, until it meets pos iterator 759 | for (ft::pair it(end() - 1, end()); 760 | it.second != pos; --it.first, --it.second) 761 | { 762 | _alloc.construct(&(*(it.first + lenMov)), *it.first); 763 | _alloc.destroy(&(*it.first)); 764 | } 765 | } 766 | 767 | /** 768 | * Move to the left all elements from a certain position until the end 769 | * of the array. Each element will be constructed/copied to his new position, 770 | * and destructed at his previous position. 771 | * 772 | * @param first Iterator pointing to the new range's beginning, elements will be 773 | * moved to this position. 774 | * @param last Iterator pointing to the first element to move. Every element after 775 | * this one until the end will be moved. 776 | */ 777 | void moveElementsToTheLeft(iterator first, iterator last) 778 | { 779 | for (; first != end(); ++first, ++last) 780 | { 781 | // Destructing the previous element to replace it by a new one. 782 | // First will destroy all the element until the end. 783 | _alloc.destroy(&(*first)); 784 | 785 | // Moving a new element to the left at first position, only if there is 786 | // still element to move 787 | if (last < end()) 788 | _alloc.construct(&(*(first)), *last); 789 | } 790 | } 791 | 792 | }; // class vector 793 | 794 | } // namespace ft 795 | 796 | #endif -------------------------------------------------------------------------------- /containers/list.hpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* list.hpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: lucaslefrancq 17 | 18 | #include "../templates/stl_like.hpp" 19 | #include "../templates/type1_or_type2.hpp" 20 | #include "../iterators/list_iterator.hpp" 21 | #include "../iterators/rev_list_iterator.hpp" 22 | 23 | namespace ft 24 | { 25 | /** 26 | * ------------------------------------------------------------- * 27 | * ------------------------- FT::LIST -------------------------- * 28 | * 29 | * - Coplien form: 30 | * (constructor): Construct list 31 | * (destructor): Destruct list 32 | * operator=: Assign list 33 | * 34 | * - Iterators: 35 | * begin: Return iterator to beginning 36 | * end: Return iterator to end 37 | * rbegin: Return reverse iterator to reverse beginning 38 | * rend: Return reverse iterator to reverse end 39 | * 40 | * - Capacity: 41 | * empty: Test whether container is empty 42 | * size: Return size 43 | * max_size: Return maximum size 44 | * 45 | * - Element access: 46 | * front: Access first element 47 | * back: Access last element 48 | * 49 | * - Modifiers: 50 | * assign: Assign new content to container 51 | * push_front: Insert element at beginning 52 | * pop_front: Delete first element 53 | * push_back: Add element at the end 54 | * pop_back: Delete last element 55 | * insert: Insert elements 56 | * erase: Erase elements 57 | * swap: Swap content 58 | * resize: Change size 59 | * clear: Clear content 60 | * 61 | * - Operations: 62 | * splice: Transfer elements from list to list 63 | * remove: Remove elements with specific value 64 | * remove_if: Remove elements fulfilling condition 65 | * unique: Remove duplicate values 66 | * merge: Merge sorted lists 67 | * sort: Sort elements in container 68 | * reverse: Reverse the order of elements 69 | * 70 | * - Non-member function overloads 71 | * relational operators: Relational operators for list 72 | * swap: Exchanges contents of two lists 73 | * ------------------------------------------------------------- * 74 | */ 75 | 76 | /** 77 | * @param T Type of container's elements. 78 | * @param Alloc Object used to manage the vector' storage. 79 | */ 80 | template > 81 | class list 82 | { 83 | /* ------------------------------------------------------------- */ 84 | /* ------------------------- ATTRIBUTES ------------------------ */ 85 | 86 | private: 87 | 88 | struct Node 89 | { 90 | T content; // Element of the list 91 | Node* prev; // Pointer to previous node 92 | Node* next; // Pointer to next node 93 | }; 94 | 95 | 96 | /* ------------------------------------------------------------- */ 97 | /* -------------------------- ALIASES -------------------------- */ 98 | 99 | public: 100 | 101 | typedef T value_type; 102 | typedef Alloc allocator_type; 103 | typedef long int difference_type; 104 | typedef size_t size_type; 105 | 106 | typedef T& reference; 107 | typedef const T& const_reference; 108 | typedef T* pointer; 109 | typedef const T* const_pointer; 110 | 111 | typedef typename ft::list_iterator iterator; 112 | typedef typename ft::list_iterator const_iterator; 113 | 114 | typedef typename ft::rev_list_iterator reverse_iterator; 115 | typedef typename ft::rev_list_iterator const_reverse_iterator; 116 | 117 | 118 | /* ------------------------------------------------------------- */ 119 | /* ------------------------- ATTRIBUTES ------------------------ */ 120 | 121 | private: 122 | 123 | Node* _endList; // Pointer to the neutral element of the circle linked list 124 | size_type _size; // Number of T values inside the list 125 | Alloc _allocT; // Copy of allocator_type object 126 | ft::allocator _allocNode; // Node's allocator 127 | 128 | 129 | /* ------------------------------------------------------------- */ 130 | /* ------------------------ COPLIEN FORM ----------------------- */ 131 | 132 | public: 133 | 134 | /** 135 | * Default constructor, creates a list with a size of 0. Initalizes an end node 136 | * pointing to itself. 137 | * 138 | * @param alloc The template param used for the allocation. 139 | */ 140 | explicit list (const allocator_type& alloc = allocator_type()) : 141 | _size(0), _allocT(alloc) 142 | { 143 | newEndNode(); 144 | } 145 | 146 | /** 147 | * Fill constructor, creates a list with a size of n and initializes the 148 | * values. 149 | * 150 | * @param n The number of elements that will be created. 151 | * @param val The value used for initialization (value initialized by default). 152 | * @param alloc The template param used for the allocation. 153 | */ 154 | explicit list (size_type n, const value_type& val = value_type(), 155 | const allocator_type& alloc = allocator_type()) : 156 | _size(0), _allocT(alloc) 157 | { 158 | newEndNode(); 159 | 160 | while (_size < n) 161 | push_back(val); 162 | } 163 | 164 | /** 165 | * Range constructor, creates a list with a size equal to the range between two 166 | * iterators and copy the values of this range to the new elements created. 167 | * 168 | * @param first An iterator representing first element of the range. 169 | * @param last An iterator indicating end of the range (will be excluded and not copied). 170 | * @param alloc The template param used for the allocation. 171 | */ 172 | template 173 | list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type(), 174 | typename ft::enable_if::value >::type* = 0) : 175 | _size(0), _allocT(alloc) 176 | { 177 | newEndNode(); 178 | 179 | for (; first != last; ++first) 180 | push_back(*first); 181 | } 182 | 183 | /** 184 | * Copy constructor, creates a list with the same size and copy/construct 185 | * all x values to the new elements allocated. 186 | * 187 | * @param x The list that will be copied. 188 | */ 189 | list (const list& x) : 190 | _size(0), _allocT(x._allocT), _allocNode(x._allocNode) 191 | { 192 | newEndNode(); 193 | 194 | for (const_iterator it = x.begin(); it != x.end(); ++it) 195 | push_back(*it); 196 | } 197 | 198 | /** 199 | * Destructor, destroys and deallocates all the list's elements and list's nodes, 200 | * including end node. 201 | */ 202 | ~list() 203 | { 204 | while (_size > 0) 205 | pop_back(); 206 | _allocNode.deallocate(_endList, 1); 207 | } 208 | 209 | /** 210 | * Assigns a list to this list. Calls the copy constructor to do the 211 | * assignment(copy and swap idiom). 212 | * 213 | * @param x The list that will be assigned. 214 | */ 215 | list& operator= (const list& x) 216 | { 217 | list copy(x); 218 | this->swap(copy); 219 | 220 | return *this; 221 | } 222 | 223 | 224 | /* ------------------------------------------------------------- */ 225 | /* ------------------------- ITERATORS ------------------------- */ 226 | 227 | /** 228 | * @return An iterator pointing to the first node of the list. 229 | */ 230 | iterator begin() { return !_size ? iterator(_endList) : 231 | iterator(_endList->next); } 232 | 233 | /** 234 | * @return A const_iterator pointing to the first element of the list. 235 | */ 236 | const_iterator begin() const { return !_size ? iterator(_endList) : 237 | iterator(_endList->next); } 238 | 239 | /** 240 | * @return An iterator pointing to the list end node. Access this 241 | * iterator will result in undefined behavior. 242 | */ 243 | iterator end() { return iterator(_endList); } 244 | 245 | /** 246 | * @return An const_iterator pointing to the list end node. Access this 247 | * iterator will result in undefined behavior. 248 | */ 249 | const_iterator end() const { return const_iterator(_endList); } 250 | 251 | /** 252 | * @return A reverse_iterator pointing to the last element of the list. 253 | * This is list end node if the list is empty. 254 | */ 255 | reverse_iterator rbegin() { return !_size ? reverse_iterator(_endList) : 256 | reverse_iterator(_endList->prev); } 257 | 258 | /** 259 | * @return A const_reverse_iterator pointing to the last element of the list. 260 | * This is list end node if the list is empty. 261 | */ 262 | const_reverse_iterator rbegin() const { return !_size ? const_reverse_iterator(_endList) : 263 | const_reverse_iterator(_endList->prev); } 264 | 265 | /** 266 | * @return A reverse_iterator pointing before the first element of the list 267 | * (so pointing to list end node because this is a circular linked list). 268 | * Access this iterator will result in undefined behavior. 269 | */ 270 | reverse_iterator rend() { return reverse_iterator(_endList); } 271 | 272 | /** 273 | * @return A const_reverse_iterator pointing before the first element of the list 274 | * (so pointing to list end node because this is a circular linked list). 275 | * Access this iterator will result in undefined behavior. 276 | */ 277 | const_reverse_iterator rend() const { return const_reverse_iterator(_endList); } 278 | 279 | 280 | /* ------------------------------------------------------------- */ 281 | /* -------------------------- CAPACITY ------------------------- */ 282 | 283 | /** 284 | * @return True if the list' size is equal to 0. 285 | */ 286 | bool empty() const { return _size == 0; } 287 | 288 | /** 289 | * @return The size of the list. 290 | */ 291 | size_type size() const { return _size; } 292 | 293 | /** 294 | * @return The max possible size to be allocated. 295 | */ 296 | size_type max_size() const 297 | { 298 | if (sizeof(value_type) == 1) 299 | return static_cast(pow(2.0, 64.0) / 2.0) - 1; 300 | return static_cast(pow(2.0, 64.0) / static_cast(sizeof(value_type))) - 1; 301 | } 302 | 303 | 304 | /* ------------------------------------------------------------- */ 305 | /* ---------------------- ELEMENTS ACCESS ---------------------- */ 306 | 307 | /** 308 | * Access first list's element. Undefined behavior if the list is empty. 309 | * 310 | * @return A reference to the first list's element. 311 | */ 312 | reference front() { return _endList->next->content; } 313 | 314 | /** 315 | * Access first list's element. Undefined behavior if the list is empty. 316 | * 317 | * @return A const reference to the first list's element. 318 | */ 319 | const_reference front() const { return _endList->next->content; } 320 | 321 | /** 322 | * Access last list's element. Undefined behavior if the list is empty. 323 | * 324 | * @return A reference to the last list's element. 325 | */ 326 | reference back() { return _endList->prev->content; } 327 | 328 | /** 329 | * Access last list's element. Undefined behavior if the list is empty. 330 | * 331 | * @return A const reference to the last list's element. 332 | */ 333 | const_reference back() const { return _endList->prev->content; } 334 | 335 | 336 | /* ------------------------------------------------------------- */ 337 | /* ------------------------- MODIFIERS ------------------------- */ 338 | 339 | /** 340 | * Assigns new contents to the list, replacing its current content, 341 | * and modifying its size accordingly.The new contents are elements constructed 342 | * from each of the elements in the range between first and last iterators. 343 | * 344 | * @param n Number of new elements constructed. 345 | * @param val Each new elements will be copy constructed from val. 346 | */ 347 | template 348 | void assign (InputIterator first, InputIterator last) 349 | { 350 | size_type i = 0; 351 | for (iterator it = begin(); first != last; ++it, ++i, ++first) 352 | { 353 | // If list is to small, creating new Nodes 354 | if (i >= _size) 355 | push_back(*first); 356 | 357 | // If element already exist, just replacing his content 358 | else 359 | { 360 | _allocT.destroy(&(*it)); 361 | _allocT.construct(&(*it), *first); 362 | } 363 | } 364 | 365 | // Destroying remaining Nodes if list is taller than assignment size 366 | while (_size > i) 367 | pop_back(); 368 | } 369 | 370 | /** 371 | * Assigns new contents to the list, replacing its current content, 372 | * and modifying its size accordingly. 373 | * 374 | * @param n Number of new elements constructed. 375 | * @param val Each new elements will be copy constructed from val. 376 | */ 377 | void assign (size_type n, const value_type& val) 378 | { 379 | size_type i = 0; 380 | for (iterator it = begin(); i < n; ++it, ++i) 381 | { 382 | // If list is to small, creating new Nodes 383 | if (i >= _size) 384 | push_back(val); 385 | 386 | // If element already exist, just replacing his content 387 | else 388 | { 389 | _allocT.destroy(&(*it)); 390 | _allocT.construct(&(*it), val); 391 | } 392 | } 393 | 394 | // Destroying remaining Nodes if list is taller than assignment size 395 | while (_size > i) 396 | pop_back(); 397 | } 398 | 399 | /** 400 | * Adds a new element at the beginning of the list, after its current first element. 401 | * Size is increased. If list is empty, the new element is still inserted as first 402 | * list element. 403 | * 404 | * @param val The new element will be copy constructed from val. 405 | */ 406 | void push_front (const value_type& val) 407 | { 408 | Node* tmp = createNode(val); 409 | 410 | tmp->prev = _endList; 411 | tmp->next = _endList->next; 412 | _endList->next->prev = tmp; 413 | _endList->next = tmp; 414 | 415 | ++_size; 416 | } 417 | 418 | /** 419 | * Removes the first element in the list, reducing the container size by one. 420 | * This destroys the removed element. Does nothing if the list is empty. 421 | */ 422 | void pop_front() 423 | { 424 | if (_size) 425 | deleteNode(_endList->next); 426 | } 427 | 428 | /** 429 | * Adds a new element at the end of the list, after its current last element. 430 | * Size is increased. If list is empty, the new element becomes first list element. 431 | * 432 | * @param val The new element will be copy constructed from val. 433 | */ 434 | void push_back (const value_type& val) 435 | { 436 | Node* tmp = createNode(val); 437 | 438 | tmp->prev = _endList->prev; 439 | tmp->next = _endList; 440 | _endList->prev->next = tmp; 441 | _endList->prev = tmp; 442 | 443 | ++_size; 444 | } 445 | 446 | /** 447 | * Removes the last element in the list, reducing the container size by one. 448 | * This destroys the removed element. Does nothing if the list is empty. 449 | */ 450 | void pop_back() 451 | { 452 | if (_size) 453 | deleteNode(_endList->prev); 454 | } 455 | 456 | /** 457 | * Inserts 1 element with a value of val at a position, and increases the list' size. 458 | * 459 | * @param position The element will be inserted just before this position. 460 | * @param val Value of the element inserted. 461 | * @return An iterator on the newly element inserted. 462 | */ 463 | iterator insert (iterator position, const value_type& val) 464 | { 465 | Node* newNode = createNode(val); 466 | 467 | // Linking new Node between position and position -1 468 | newNode->prev = position.getNode()->prev; 469 | newNode->next = position.getNode()->prev->next; 470 | 471 | // Linking position and position -1 to new element 472 | newNode->prev->next = newNode; 473 | newNode->next->prev = newNode; 474 | 475 | ++_size; 476 | return iterator(--position); 477 | } 478 | 479 | /** 480 | * Inserts n elements with a value of val at a position, and increases the list' size. 481 | * 482 | * @param position Elements will be inserted just before this position. 483 | * @param n Number of elements to be inserted. 484 | * @param val Value of the elements inserted. 485 | */ 486 | void insert (iterator position, size_type n, const value_type& val) 487 | { 488 | while (n-- > 0) 489 | position = insert(position, val); 490 | } 491 | 492 | /** 493 | * Inserts all elements between first and last, and increases the vector' size. 494 | * 495 | * @param position Elements will be inserted just before this position. 496 | * @param first An iterator pointing to the range's beginning (will be included). 497 | * @param last An iterator pointing to the range's end (will not be included). 498 | */ 499 | template 500 | void insert (iterator position, InputIterator first, InputIterator last, 501 | typename ft::enable_if::value >::type* = 0) 502 | { 503 | // Inserting in reverse order 504 | for (ft::pair it(last, first); 505 | it.first != it.second; ++it.first) 506 | position = insert(position, *it.first); 507 | } 508 | 509 | /** 510 | * Removes from the list one element at a specific position. Size is decreased. 511 | * 512 | * @param position Iterator pointing to a single element to be removed from the list. 513 | * @return An iterator pointing to the element that followed the last element 514 | * erased by the function call. This is the container end if the operation 515 | * erased the last element in the sequence. 516 | */ 517 | iterator erase (iterator position) 518 | { 519 | // Using iterator's Node constructor for creating last 520 | return erase(position, position.getNode()->next); 521 | } 522 | 523 | /** 524 | * Removes from the list a range of elements. Size is decreased by the number of 525 | * elements removed. 526 | * 527 | * @param first An iterator pointing to the range's beginning (will be included). 528 | * @param last An iterator pointing to the range's end (will not be included). 529 | * @return An iterator pointing to the element that followed the last element 530 | * erased by the function call. This is the container end if the operation 531 | * erased the last element in the sequence. 532 | */ 533 | iterator erase (iterator first, iterator last) 534 | { 535 | for (; first != last;) 536 | deleteNode((++first).getNode()->prev); 537 | return last; 538 | } 539 | 540 | /** 541 | * Swaps a list with the content of this one. 542 | * 543 | * @param x The list to be swapped. 544 | */ 545 | void swap (list& x) 546 | { 547 | swap(_size, x._size); 548 | swap(_endList, x._endList); 549 | swap(_allocT, x._allocT); 550 | swap(_allocNode, x._allocNode); 551 | } 552 | 553 | /** 554 | * Resizes the list so that it contains n elements. Push_back or pop_back will occured 555 | * depending if elements need to be added or removed. 556 | * 557 | * @param n The number of elements that the list will contain after beeing resized. 558 | * @param val If new elements need to be added, they will be initialize with val 559 | * (value initialize by default). 560 | */ 561 | void resize (size_type n, value_type val = value_type()) 562 | { 563 | while (n > _size) 564 | push_back(val); 565 | while (n < _size) 566 | pop_back(); 567 | } 568 | 569 | /** 570 | * Removes all elements from the list (which are destroyed), leaving the 571 | * container with a size of 0. List end node is still existing. 572 | */ 573 | void clear() 574 | { 575 | while (_size) 576 | pop_back(); 577 | } 578 | 579 | 580 | /* ------------------------------------------------------------- */ 581 | /* ------------------------ OPERATIONS ------------------------- */ 582 | 583 | /** 584 | * Transfering the entire x list at a certain position in this list. This effectively inserts 585 | * those elements into the container and removes them from x, altering the sizes of both containers. 586 | * 587 | * @param position Position within the container where the elements of x are inserted. 588 | * @param x A list object of the same type. 589 | */ 590 | void splice (iterator position, list& x) 591 | { 592 | while (x.size()) 593 | splice(position, x, x.begin()); 594 | } 595 | 596 | /** 597 | * Transfering one x element at a certain position in this list. This effectively inserts 598 | * those elements into the container and removes them from x, altering the sizes of both containers. 599 | * 600 | * @param position Position within the container where the elements of x are inserted. 601 | * @param x A list object of the same type. 602 | * @param i Iterator to an element in x. Only this single element is transferred. 603 | */ 604 | void splice (iterator position, list& x, iterator i) 605 | { 606 | Node* tmp = i.getNode(); 607 | 608 | // Linking previous and next node in x together 609 | tmp->next->prev = tmp->prev; 610 | tmp->prev->next = tmp->next; 611 | 612 | // Linking i in this list 613 | tmp->prev = position.getNode()->prev; 614 | tmp->next = position.getNode(); 615 | position.getNode()->prev->next = tmp; 616 | position.getNode()->prev = tmp; 617 | 618 | --x._size; 619 | ++_size; 620 | } 621 | 622 | /** 623 | * Transfering a range of x elements at a certain position in this list. This effectively 624 | * inserts those elements into the container and removes them from x, altering the 625 | * sizes of both containers. 626 | * 627 | * @param position Position within the container where the elements of x are inserted. 628 | * @param x A list object of the same type. 629 | * @param first Iterator pointing to the first range's element inside x (will be transfered). 630 | * @param last Iterator pointing to the last range's element inside x (will not be transfered). 631 | */ 632 | void splice (iterator position, list& x, iterator first, iterator last) 633 | { 634 | if (first == last) 635 | return; 636 | 637 | if (first.getNode()->next == last.getNode()) 638 | splice(position, x, first); 639 | else 640 | { 641 | // Counting range' size 642 | size_type rangeSize = 0; 643 | for (iterator tmp(first); tmp != last; ++tmp) 644 | ++rangeSize; 645 | 646 | // Saving last range's elem 647 | iterator lastRangeElem(last.getNode()->prev); 648 | 649 | // Removing range from list x 650 | first.getNode()->prev->next = last.getNode(); 651 | last.getNode()->prev = first.getNode()->prev; 652 | 653 | // Linking range in this list 654 | first.getNode()->prev = position.getNode()->prev; 655 | lastRangeElem.getNode()->next = position.getNode(); 656 | position.getNode()->prev->next = first.getNode(); 657 | position.getNode()->prev = lastRangeElem.getNode(); 658 | 659 | x._size -= rangeSize; 660 | _size += rangeSize; 661 | } 662 | } 663 | 664 | /** 665 | * Removes from the container all the elements that compare equal to val. This calls the 666 | * destructor of these objects and reduces the container size by the number of elements removed. 667 | * 668 | * @param val Value of the elements to be removed. 669 | */ 670 | void remove (const value_type& val) 671 | { 672 | for (iterator it = end(); it.getNode()->next != end().getNode();) 673 | { 674 | if (it.getNode()->next->content == val) 675 | deleteNode(it.getNode()->next); 676 | else 677 | ++it; 678 | } 679 | } 680 | 681 | /** 682 | * Removes from the container all the elements for which Predicate pred returns true. This calls the 683 | * destructor of these objects and reduces the container size by the number of elements removed. 684 | * 685 | * @param pred Unary predicate that takes a value of the same type as those contained 686 | * in the list and returns true or false (when true occured for an element, 687 | * this one will be removed). 688 | */ 689 | template 690 | void remove_if (Predicate pred) 691 | { 692 | for (iterator it = end(); it.getNode()->next != end().getNode();) 693 | { 694 | if (pred(it.getNode()->next->content)) 695 | deleteNode(it.getNode()->next); 696 | else 697 | ++it; 698 | } 699 | } 700 | 701 | /** 702 | * Removes all but the first element from every consecutive group of equal elements in the container. 703 | */ 704 | void unique() 705 | { 706 | for (iterator it = end(); it.getNode()->next != end().getNode();) 707 | { 708 | if (it != end() && *it == it.getNode()->next->content) 709 | deleteNode(it.getNode()->next); 710 | else 711 | ++it; 712 | } 713 | } 714 | 715 | /** 716 | * Removes all but the first element from every consecutive group in the container 717 | * for which the binary predicate will return true. 718 | * 719 | * @param binary_pred Binary predicate that takes two values of the same type than those contained 720 | * in the list and returns true to remove the element passed as first argument, 721 | * false otherwise. 722 | */ 723 | template 724 | void unique (BinaryPredicate binary_pred) 725 | { 726 | for (iterator it = end(); it.getNode()->next->next != end().getNode();) 727 | { 728 | if (binary_pred(it.getNode()->next->content, it.getNode()->next->next->content)) 729 | deleteNode(it.getNode()->next->next); 730 | else 731 | ++it; 732 | } 733 | } 734 | 735 | /** 736 | * Merges x into the list by transferring all of its elements at their respective ordered positions 737 | * into the container (both containers shall already be ordered). The comparison between the two 738 | * list elements is done by using operator<. This empty x list. 739 | * 740 | * @param x A list object of the same type. 741 | */ 742 | void merge (list& x) 743 | { 744 | if (&x == this) 745 | return ; 746 | 747 | iterator thisIt = end(); 748 | 749 | // Starting from the end, until all elements in x are removed and only 750 | // end element remained, pointing to itself 751 | for (iterator xIt = x.end(); xIt.getNode()->next != x.end().getNode();) 752 | { 753 | // If we reached end of this list or if comp is true 754 | if (thisIt.getNode()->next == end().getNode() || 755 | xIt.getNode()->next->content < thisIt.getNode()->next->content) 756 | { 757 | // Splicing new element and iterator in this list will be pointing on it 758 | splice(thisIt.getNode()->next, x, xIt.getNode()->next); 759 | ++thisIt; 760 | } 761 | else 762 | ++thisIt; 763 | } 764 | } 765 | 766 | /** 767 | * Merges x into the list by transferring all of its elements at their respective ordered positions 768 | * into the container (both containers shall already be ordered). The comparison between the two 769 | * list elements is done by using a binary predicate. This empty x list. 770 | * 771 | * @param x A list object of the same type. 772 | * @param comp Binary predicate that, taking two values of the same type than those contained in the list, 773 | * returns true if the first argument is considered to go before the second, and false otherwise. 774 | */ 775 | template 776 | void merge (list& x, Compare comp) 777 | { 778 | if (&x == this) 779 | return ; 780 | 781 | iterator thisIt = end(); 782 | 783 | // Starting from the end, until all elements in x are removed and only 784 | // end element remained, pointing to itself 785 | for (iterator xIt = x.end(); xIt.getNode()->next != x.end().getNode();) 786 | { 787 | // If we reached end of this list or if comp is true 788 | if (thisIt.getNode()->next == end().getNode() || 789 | comp(xIt.getNode()->next->content, thisIt.getNode()->next->content)) 790 | { 791 | // Splicing new element and iterator in this list will be pointing on it 792 | splice(thisIt.getNode()->next, x, xIt.getNode()->next); 793 | ++thisIt; 794 | } 795 | else 796 | ++thisIt; 797 | } 798 | } 799 | 800 | 801 | /** 802 | * Sorts the elements in the list using operator<. The nodes with their content are moved, 803 | * none element is destructed / copy constructed. 804 | */ 805 | void sort() 806 | { 807 | for (iterator it = begin(); it.getNode()->next != end().getNode(); ++it) 808 | { 809 | iterator tmp(it); 810 | 811 | // Checking if there is a value inf to it after it 812 | for (iterator min(it.getNode()->next); min != end(); ++min) 813 | if (*min < *tmp) 814 | tmp = min; 815 | 816 | // Swapping it and the inf node and restarting to search 817 | // inf values from the node that was swapped 818 | if (*tmp < *it) 819 | { 820 | swap2Nodes(tmp.getNode(), it.getNode()); 821 | it = tmp; 822 | } 823 | } 824 | } 825 | 826 | /** 827 | * Sorts the elements in the list using a binary predicate. The nodes with their content 828 | * are moved, none element is destructed / copy constructed. 829 | * 830 | * @param comp Binary predicate that, taking two values of the same type than those contained in the list, 831 | * returns true if the first argument is considered to go before the second, and false otherwise. 832 | */ 833 | template 834 | void sort (Compare comp) 835 | { 836 | for (iterator it = begin(); it.getNode()->next != end().getNode(); ++it) 837 | { 838 | iterator tmp(it); 839 | 840 | // Checking if there is a value inf to it after it 841 | for (iterator min(it.getNode()->next); min != end(); ++min) 842 | if (comp(*min, *tmp)) 843 | tmp = min; 844 | 845 | // Swapping it and the inf node and restarting to search 846 | // inf values from the node that was swapped 847 | if (comp(*tmp, *it)) 848 | { 849 | swap2Nodes(tmp.getNode(), it.getNode()); 850 | it = tmp; 851 | } 852 | } 853 | } 854 | 855 | /** 856 | * Reverse the list. Each node from the beginning will be inserted from the 857 | * end of the list one in front of the other. 858 | */ 859 | void reverse() 860 | { 861 | if (_size > 1) 862 | { 863 | Node* insertBefore = _endList; 864 | Node* tmp; 865 | 866 | while (_endList->next != insertBefore) 867 | { 868 | // First Node that will be move before Node insertBefore 869 | tmp = _endList->next; 870 | 871 | // Linking _endList and Node "_endList + 2" 872 | _endList->next = tmp->next; 873 | tmp->next->prev = _endList; 874 | 875 | // Moving first Node between Node insertBefore 876 | // and Node "insertBefore - 1" 877 | tmp->next = insertBefore; 878 | tmp->prev = insertBefore->prev; 879 | tmp->prev->next = tmp; 880 | tmp->next->prev = tmp; 881 | 882 | // Node insertBefore is now pointing to the Node we moved 883 | insertBefore = tmp; 884 | } 885 | } 886 | } 887 | 888 | 889 | /* ------------------------------------------------------------- */ 890 | /* --------------- NON-MEMBER FUNCTION OVERLOADS --------------- */ 891 | 892 | /** 893 | * @return True if the 2 vectors have same size and same content. 894 | */ 895 | friend bool operator==(const list& lhs, const list& rhs) 896 | { 897 | if (lhs.size() != rhs.size()) 898 | return false; 899 | 900 | for (ft::pair it(lhs.begin(), rhs.begin()); 901 | it.first != lhs.end(); ++it.first, ++it.second) 902 | if (*(it.first) != *(it.second)) 903 | return false; 904 | return true; 905 | } 906 | 907 | /** 908 | * @return True if the 2 vectors have different size or different content. 909 | */ 910 | friend bool operator!=(const list& lhs, const list& rhs) { return !(lhs == rhs); } 911 | 912 | /** 913 | * Compares the elements sequentially using operator< and stopping at the 914 | * first occurrence. 915 | * 916 | * @return True if all lhs' elements are < to rhs' elements, or if 917 | * lhs' content == rhs' content and lhs' size < rhs' size. 918 | */ 919 | friend bool operator<(const list& lhs, const list& rhs) 920 | { 921 | for (ft::pair it(lhs.begin(), rhs.begin()); 922 | it.first != lhs.end() && it.second != rhs.end(); ++it.first, ++it.second) 923 | if (*(it.first) < *(it.second)) 924 | return true; 925 | return (lhs.size() < rhs.size()); 926 | } 927 | 928 | /** 929 | * Uses operator< to compare the 2 vectors (rhs < lhs). 930 | * 931 | * @return True if all lhs' elements are > to all rhs' elements, or if 932 | * lhs' content == rhs' content and lhs' size > rhs' size. 933 | */ 934 | friend bool operator> (const list& lhs, const list& rhs) { return rhs < lhs; } 935 | 936 | /** 937 | * Uses operator< to compare the 2 vectors !(rhs < lhs). 938 | * 939 | * @return True if all lhs' elements are <= to all rhs' elements, or if 940 | * lhs' content == rhs' content and lhs' size <= rhs' size. 941 | */ 942 | friend bool operator<=(const list& lhs, const list& rhs) { return !(rhs < lhs); } 943 | 944 | /** 945 | * Uses operator< to compare the 2 vectors !(lhs < rhs). 946 | * 947 | * @return True if all lhs' elements are >= to all rhs' elements, or if 948 | * lhs' content == rhs' content and lhs' size >= rhs' size. 949 | */ 950 | friend bool operator>= (const list& lhs, const list& rhs) { return !(lhs < rhs); } 951 | 952 | /** 953 | * Swaps the content of two vectors. 954 | * 955 | * @param x Will be swap with y. 956 | * @param y Will be swap with x. 957 | */ 958 | friend void swap(list& x, list& y) { x.swap(y); } 959 | 960 | 961 | /* ------------------------------------------------------------- */ 962 | /* ------------------ PRIVATE MEMBER FUNCTIONS ----------------- */ 963 | 964 | private: 965 | 966 | /** 967 | * Create a new endNode. Data isn't constructed. 968 | */ 969 | void newEndNode() 970 | { 971 | _endList = _allocNode.allocate(1); 972 | _endList->next = _endList; 973 | _endList->prev = _endList; 974 | } 975 | 976 | /** 977 | * Destroy Node's content and then deallocate the Node. 978 | * 979 | * @param toDelete The Node to destroy and deallocate. 980 | */ 981 | void deleteNode(Node *toDelete) 982 | { 983 | // Linking previous and next element together 984 | toDelete->prev->next = toDelete->next; 985 | toDelete->next->prev = toDelete->prev; 986 | 987 | _allocT.destroy(&toDelete->content); 988 | _allocNode.deallocate(toDelete, 1); 989 | 990 | --_size; 991 | } 992 | 993 | /** 994 | * Allocate a new Node and copy construct his content from val. 995 | * 996 | * @param val The content to copy construct. 997 | * @return The Node newly created. 998 | */ 999 | Node* createNode(const value_type& val = value_type()) 1000 | { 1001 | Node *newNode = _allocNode.allocate(1); 1002 | _allocT.construct(&newNode->content, val); 1003 | 1004 | return newNode; 1005 | } 1006 | 1007 | /** 1008 | * Swap two nodes by exchanging their previous and next Node*. 1009 | * 1010 | * @param a Will be swap with b. 1011 | * @param b Will be swap with a. 1012 | */ 1013 | void swap2Nodes(Node *a, Node *b) 1014 | { 1015 | // If a and b are neighbor nodes but b is before a, 1016 | // reversing them so a is always before b 1017 | if (a->prev == b) 1018 | swap(a, b); 1019 | 1020 | // Saving elements next to a 1021 | Node *aPrev = a->prev; 1022 | Node *aNext = a->next; 1023 | 1024 | // Case a and b aren't neighbor nodes 1025 | if (a->next != b) 1026 | { 1027 | // Switching a to b position, between prev and next elem to b 1028 | a->prev = b->prev; 1029 | a->next = b->next; 1030 | b->next->prev = a; 1031 | b->prev->next = a; 1032 | 1033 | // Switching a to b position, between prev and next elem to a 1034 | b->prev = aPrev; 1035 | b->next = aNext; 1036 | aPrev->next = b; 1037 | aNext->prev = b; 1038 | } 1039 | 1040 | // Case a and b are neighbor nodes 1041 | else 1042 | { 1043 | // switching a to b position 1044 | a->prev = b; 1045 | a->next = b->next; 1046 | b->next->prev = a; 1047 | 1048 | // Switching b to a position 1049 | b->prev = aPrev; 1050 | aPrev->next = b; 1051 | b->next = a; 1052 | } 1053 | } 1054 | 1055 | /** 1056 | * Swaps two variables using references. 1057 | * 1058 | * @param a Will be swap with b. 1059 | * @param b Will be swap with a. 1060 | */ 1061 | template 1062 | void swap(U& a, U& b) 1063 | { 1064 | U tmp = a; 1065 | a = b; 1066 | b = tmp; 1067 | } 1068 | 1069 | }; // class list 1070 | 1071 | } // namespace ft 1072 | 1073 | #endif --------------------------------------------------------------------------------