├── .gitignore ├── .gitmessage.txt ├── .vscode ├── c_cpp_properties.json ├── launch.json ├── settings.json └── tasks.json ├── Makefile ├── README.md ├── asset ├── RBtree_explain.png ├── child_alloc.png ├── iterator.png ├── iterator_traits.png ├── map.png ├── parent_alloc.png ├── rb-tree.pdf ├── rbt_class.png ├── set.png └── vector.png ├── include ├── __tree.hpp ├── algorithm.hpp ├── iterator.hpp ├── map.hpp ├── set.hpp ├── stack.hpp ├── test.hpp ├── type_traits.hpp ├── utility.hpp └── vector.hpp ├── src ├── __tree.cpp └── main.cpp └── tests ├── alloc_test.cpp ├── functor_test.cpp ├── iterator_test.cpp ├── map_test.cpp ├── pair_test.cpp ├── raii_test.cpp ├── set_test.cpp ├── stack_test.cpp ├── testtest.cpp ├── throw_test.cpp ├── tree_test.cpp ├── type_traits.cpp └── vector_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/c++,c 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=c++,c 4 | 5 | ### C ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Object files 10 | *.o 11 | *.ko 12 | *.obj 13 | *.elf 14 | 15 | # Linker output 16 | *.ilk 17 | *.map 18 | *.exp 19 | 20 | # Precompiled Headers 21 | *.gch 22 | *.pch 23 | 24 | # Libraries 25 | *.lib 26 | *.a 27 | *.la 28 | *.lo 29 | 30 | # Shared objects (inc. Windows DLLs) 31 | *.dll 32 | *.so 33 | *.so.* 34 | *.dylib 35 | 36 | # Executables 37 | *.exe 38 | *.out 39 | *.app 40 | *.i*86 41 | *.x86_64 42 | *.hex 43 | 44 | # Debug files 45 | *.dSYM/ 46 | *.su 47 | *.idb 48 | *.pdb 49 | 50 | # Kernel Module Compile Results 51 | *.mod* 52 | *.cmd 53 | .tmp_versions/ 54 | modules.order 55 | Module.symvers 56 | Mkfile.old 57 | dkms.conf 58 | 59 | ### C++ ### 60 | # Prerequisites 61 | 62 | # Compiled Object files 63 | *.slo 64 | 65 | # Precompiled Headers 66 | 67 | # Compiled Dynamic libraries 68 | 69 | # Fortran module files 70 | *.mod 71 | *.smod 72 | 73 | # Compiled Static libraries 74 | *.lai 75 | 76 | # Executables 77 | 78 | # End of https://www.toptal.com/developers/gitignore/api/c++,c 79 | containers 80 | containers_test 81 | .DS_Store 82 | TODO__ERASE__PRINT__TREE__ 83 | -------------------------------------------------------------------------------- /.gitmessage.txt: -------------------------------------------------------------------------------- 1 | # (gitmoji) : [ft_containers]<issue number(optional)> 2 | 3 | ##### 제목은 이슈 번호와 함께 최대 50 글자까지 한 줄로 입력 ############## -> | 4 | 5 | # 본문은 위에 작성 6 | ######## 본문은 한 줄에 최대 72 글자까지만 입력 ########################### -> | 7 | 8 | # --- COMMIT END --- 9 | # <타입> 리스트 10 | # ✨(:sparkles:) feat : 기능 (새로운 기능) 11 | # 🐛(:bug:) fix : 버그 (버그 수정) 12 | # ♻(:recycle:) refactor : 리팩토링 13 | # 📝(:memo:) docs : 문서 (문서 추가, 수정, 삭제) 14 | # ✅(:white_check_mark:) test : 테스트 (테스트 코드 추가, 수정, 삭제: 비즈니스 로직에 변경 없음) 15 | # 🔨(:hammer:) chore : 기타 변경사항 (빌드 스크립트 수정 등) 16 | # ------------------ 17 | # 제목은 명령문으로 18 | # 제목 끝에 마침표(.) 금지 19 | # 제목과 본문을 한 줄 띄워 분리하기 20 | # 본문은 "어떻게" 보다 "무엇을", "왜"를 설명한다. 21 | # 본문은 한 줄을 작성하고 . 마침표를 찍어서 분리한다. 22 | # ------------------ 23 | # gitmoji list 24 | # ⚡️(:zap:) 🔥(:fire:) 🚀 (:rocket:) 🎉 (:tada:) 🚧 (:construction:) 25 | # ✏️ (:pencil2:) 💡 (:bulb:) 😭 sad... 26 | # git config --local commit.template .gitmessage.txt 27 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "${workspaceFolder}/include" 8 | ], 9 | "defines": [], 10 | "macFrameworkPath": [ 11 | "/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks" 12 | ], 13 | "compilerPath": "/usr/bin/clang", 14 | "cStandard": "c11", 15 | "cppStandard": "c++98", 16 | "intelliSenseMode": "macos-clang-x64" 17 | } 18 | ], 19 | "version": 4 20 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(lldb) Launch", 9 | "type": "lldb", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/containers", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${fileDirname}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "lldb", 18 | "preLaunchTask": "Use Makefile" 19 | }, 20 | { 21 | "name": "(lldb) Launch tests", 22 | "type": "lldb", 23 | "request": "launch", 24 | "program": "${workspaceFolder}/mine.out", 25 | "args": [ 26 | "asbc", 27 | "aff", 28 | "v", 29 | "ghdfg", 30 | "dsfgdfhdfh", 31 | ], 32 | "stopAtEntry": false, 33 | "cwd": "${fileDirname}", 34 | "environment": [], 35 | "externalConsole": false, 36 | "MIMode": "lldb", 37 | } 38 | ], 39 | "inputs": [ 40 | { 41 | "id": "filename", 42 | "description": "put filename from workspaceFolder", 43 | "default": "", 44 | "type": "promptString" 45 | }, 46 | { 47 | "id": "argv", 48 | "description": "put argv", 49 | "default": "", 50 | "type": "promptString" 51 | }, 52 | ] 53 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iostream": "cpp", 4 | "ios": "cpp", 5 | "istream": "cpp", 6 | "streambuf": "cpp", 7 | "__config": "cpp", 8 | "iosfwd": "cpp", 9 | "__bit_reference": "cpp", 10 | "__debug": "cpp", 11 | "__errc": "cpp", 12 | "__functional_base": "cpp", 13 | "__hash_table": "cpp", 14 | "__locale": "cpp", 15 | "__mutex_base": "cpp", 16 | "__node_handle": "cpp", 17 | "__nullptr": "cpp", 18 | "__split_buffer": "cpp", 19 | "__string": "cpp", 20 | "__threading_support": "cpp", 21 | "__tuple": "cpp", 22 | "algorithm": "cpp", 23 | "array": "cpp", 24 | "atomic": "cpp", 25 | "bit": "cpp", 26 | "bitset": "cpp", 27 | "cctype": "cpp", 28 | "chrono": "cpp", 29 | "clocale": "cpp", 30 | "cmath": "cpp", 31 | "complex": "cpp", 32 | "cstdarg": "cpp", 33 | "cstddef": "cpp", 34 | "cstdint": "cpp", 35 | "cstdio": "cpp", 36 | "cstdlib": "cpp", 37 | "cstring": "cpp", 38 | "ctime": "cpp", 39 | "cwchar": "cpp", 40 | "cwctype": "cpp", 41 | "exception": "cpp", 42 | "functional": "cpp", 43 | "initializer_list": "cpp", 44 | "iterator": "cpp", 45 | "limits": "cpp", 46 | "locale": "cpp", 47 | "memory": "cpp", 48 | "mutex": "cpp", 49 | "new": "cpp", 50 | "optional": "cpp", 51 | "ostream": "cpp", 52 | "ratio": "cpp", 53 | "sstream": "cpp", 54 | "stdexcept": "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 | "vector": "cpp", 64 | "__undef_macros": "cpp", 65 | "memory_resource": "cpp", 66 | "__functional_03": "cpp", 67 | "deque": "cpp", 68 | "__tree": "cpp", 69 | "map": "cpp", 70 | "stack": "cpp", 71 | "__functional_base_03": "cpp", 72 | "compare": "cpp", 73 | "__memory": "cpp", 74 | "set": "cpp", 75 | "list": "cpp", 76 | "__cxx_version": "cpp", 77 | "filesystem": "cpp", 78 | "fstream": "cpp", 79 | "queue": "cpp", 80 | "iomanip": "cpp" 81 | }, 82 | "C_Cpp.errorSquiggles": "Enabled", 83 | "cSpell.words": [ 84 | "Alloc", 85 | "cplusplus", 86 | "cppreference", 87 | "crbegin", 88 | "crend", 89 | "deallocates", 90 | "deque", 91 | "libcxx", 92 | "multiset", 93 | "NOEXCEPT", 94 | "NOEXCPT", 95 | "ptrdiff", 96 | "rbegin", 97 | "rebalance", 98 | "yongjule" 99 | ], 100 | "C_Cpp.dimInactiveRegions": true 101 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "Use Makefile", 6 | "command": "make", 7 | "args": [ 8 | "debug" 9 | ], 10 | "options": { 11 | "cwd": "${workspaceFolder}" 12 | }, 13 | "problemMatcher": [ 14 | "$gcc" 15 | ], 16 | "group": { 17 | "kind": "build", 18 | "isDefault": true 19 | }, 20 | "detail": "Task generated by Debugger." 21 | } 22 | ], 23 | "version": "2.0.0" 24 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX = c++ 2 | 3 | ifdef DEBUG 4 | CXXFLAGS = --std=c++98 -g3 -fsanitize=address 5 | else ifdef LEAKS 6 | CXXFLAGS = --std=c++98 -g 7 | else ifdef TEST 8 | CXXFLAGS = -g --std=c++98 #-fsanitize=address 9 | else 10 | CXXFLAGS = --std=c++98 -Wall -Wextra -Werror 11 | endif 12 | 13 | ifdef TEST 14 | NAME = mine.out 15 | else 16 | NAME = containers #Name of program 17 | endif 18 | 19 | INC_DIR = ./include/ 20 | 21 | SRCS_DIR = ./src/ 22 | 23 | TEST_DIR = ./tests/ 24 | 25 | SRCS = $(addprefix $(SRCS_DIR), \ 26 | __tree.cpp \ 27 | ) 28 | 29 | ifdef TEST 30 | SRCS += $(addprefix $(TEST_DIR), $(TEST).cpp) 31 | else 32 | SRCS += $(addprefix $(SRCS_DIR), main.cpp) 33 | endif 34 | 35 | OBJS = ${SRCS:%.cpp=%.o} 36 | 37 | OBJ_FILES = $(OBJS) 38 | 39 | COMPILE_MSG = @echo $(BOLD)$(L_PUPLE) 📣 ${NAME} Compiled 🥳$(RESET) 40 | 41 | ######################### Color ######################### 42 | GREEN="\033[32m" 43 | L_GREEN="\033[1;32m" 44 | RED="\033[31m" 45 | L_RED="\033[1;31m" 46 | RESET="\033[0m" 47 | BOLD="\033[1m" 48 | L_PUPLE="\033[1;35m" 49 | L_CYAN="\033[1;96m" 50 | UP = "\033[A" 51 | CUT = "\033[K" 52 | 53 | ########################## Rule ########################## 54 | 55 | .PHONY : all 56 | all : $(OBJS) $(NAME) 57 | 58 | $(NAME) : $(OBJS) 59 | @$(CXX) $(CXXFLAGS) $(OBJS) -I$(INC_DIR) -o $@ 60 | @echo $(L_CYAN) 🔗 Linking [$(notdir $^)] to [$@] $(RESET) 61 | $(COMPILE_MSG) 62 | 63 | 64 | %.o : %.cpp 65 | @$(CXX) $(CXXFLAGS) -I$(INC_DIR) -c $< -o $@ 66 | @echo $(BOLD)$(L_GREEN) Compiling with $(CXXFLAGS) -I$(INC_DIR) ...$(RESET) 67 | @echo $(GREEN) [$(notdir $^)] to [$(notdir $@)] $(RESET) 68 | 69 | .PHONY : clean 70 | clean : 71 | @rm -f $(OBJS) 72 | @echo $(L_RED) Remove🧹 OBJ files in $(NAME) 👋 $(RESET) 73 | 74 | 75 | .PHONY : fclean 76 | fclean : clean 77 | @rm -f $(NAME) 78 | @echo $(RED) Remove🧹 $(NAME) 📣 $(RESET) 79 | 80 | .PHONY : re 81 | re : fclean all 82 | 83 | .PHONY : debug 84 | debug : 85 | @make DEBUG=1 86 | @echo $(RED)$(BOLD) It\'s DEBUG TIME🤪$(RESET) 87 | 88 | .PHONY : leaks 89 | leaks : 90 | @make LEAKS=1 91 | @echo $(RED)$(BOLD) Is there Leaks?🚰$(RESET) 92 | -------------------------------------------------------------------------------- /asset/RBtree_explain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/RBtree_explain.png -------------------------------------------------------------------------------- /asset/child_alloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/child_alloc.png -------------------------------------------------------------------------------- /asset/iterator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/iterator.png -------------------------------------------------------------------------------- /asset/iterator_traits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/iterator_traits.png -------------------------------------------------------------------------------- /asset/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/map.png -------------------------------------------------------------------------------- /asset/parent_alloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/parent_alloc.png -------------------------------------------------------------------------------- /asset/rb-tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/rb-tree.pdf -------------------------------------------------------------------------------- /asset/rbt_class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/rbt_class.png -------------------------------------------------------------------------------- /asset/set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/set.png -------------------------------------------------------------------------------- /asset/vector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongjulejule/ft_containers/4ace74a37f868d992f1ab21dcc6e25e3a572ff30/asset/vector.png -------------------------------------------------------------------------------- /include/__tree.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tree.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief Red Black Tree which is base of set and map 5 | * @version 0.1 6 | * @date 2022-04-10 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef __TREE_HPP 13 | #define __TREE_HPP 14 | 15 | #include <memory> 16 | 17 | #include "algorithm.hpp" 18 | #include "iterator.hpp" 19 | #include "utility.hpp" 20 | 21 | #define FT_NOEXCEPT throw() 22 | 23 | namespace ft { 24 | /************************************************************************************* 25 | * @brief Tree Nodes member function 26 | *************************************************************************************/ 27 | 28 | enum __tree_node_color { RED = false, BLACK = true }; 29 | 30 | struct __tree_node_base; 31 | 32 | __tree_node_base *__tree_increment(__tree_node_base *__x) FT_NOEXCEPT; 33 | const __tree_node_base *__tree_increment(const __tree_node_base *__x) 34 | FT_NOEXCEPT; 35 | 36 | __tree_node_base *__tree_decrement(__tree_node_base *__x) FT_NOEXCEPT; 37 | const __tree_node_base *__tree_decrement(const __tree_node_base *__x) 38 | FT_NOEXCEPT; 39 | 40 | void __tree_rotate_left(__tree_node_base *const __x, __tree_node_base *&__root); 41 | void __tree_rotate_right(__tree_node_base *const __x, 42 | __tree_node_base *&__root); 43 | 44 | void __tree_insert_and_fixup(const bool __insert_left, __tree_node_base *__x, 45 | __tree_node_base *__p, 46 | __tree_node_base &__header) FT_NOEXCEPT; 47 | 48 | __tree_node_base *__tree_erase_and_fixup( 49 | __tree_node_base *const __z, __tree_node_base &__header) FT_NOEXCEPT; 50 | 51 | __tree_node_base *__minimum(__tree_node_base *__x) FT_NOEXCEPT; 52 | const __tree_node_base *__minimum(const __tree_node_base *__x) FT_NOEXCEPT; 53 | __tree_node_base *__maximum(__tree_node_base *__x) FT_NOEXCEPT; 54 | const __tree_node_base *__maximum(const __tree_node_base *__x) FT_NOEXCEPT; 55 | 56 | /************************************************************************************* 57 | * @brief Tree Nodes 58 | *************************************************************************************/ 59 | 60 | // base of node structure for rb-tree 61 | struct __tree_node_base { 62 | typedef __tree_node_base *_Base_ptr; 63 | typedef const __tree_node_base *_Const_base_ptr; 64 | 65 | __tree_node_color __color_; 66 | _Base_ptr __parent_; 67 | _Base_ptr __left_; 68 | _Base_ptr __right_; 69 | }; 70 | 71 | struct __tree_header { 72 | __tree_node_base __header_; 73 | std::size_t __node_count_; 74 | 75 | __tree_header() { 76 | __header_.__color_ = RED; 77 | __tree_reset(); 78 | } 79 | 80 | void __tree_reset(); 81 | void __tree_move_data(__tree_header &other); 82 | }; 83 | 84 | template <typename _Key_compare> 85 | struct __tree_key_compare { 86 | _Key_compare __key_comp; 87 | 88 | __tree_key_compare() : __key_comp() {} 89 | __tree_key_compare(const _Key_compare &other) : __key_comp(other) {} 90 | }; 91 | 92 | // Node for rb-tree 93 | template <typename _Val> 94 | struct __tree_node : public __tree_node_base { 95 | typedef __tree_node<_Val> *_Link_type; 96 | 97 | _Val __value_field; 98 | 99 | _Val *__valptr() { return &__value_field; } 100 | const _Val *__valptr() const { return &__value_field; } 101 | }; 102 | 103 | /************************************************************************************* 104 | * @brief Tree Nodes Iterator 105 | *************************************************************************************/ 106 | 107 | template <typename _T> 108 | struct __tree_iterator : public iterator<bidirectional_iterator_tag, _T> { 109 | typedef _T value_type; 110 | typedef _T &reference; 111 | typedef _T *pointer; 112 | typedef bidirectional_iterator_tag iterator_category; 113 | typedef ptrdiff_t difference_type; 114 | 115 | typedef __tree_iterator<_T> iterator_type; 116 | typedef __tree_node_base::_Base_ptr _Base_ptr; 117 | typedef __tree_node<_T> *_Link_type; 118 | 119 | _Base_ptr __node_; 120 | 121 | __tree_iterator() : __node_() {} 122 | 123 | __tree_iterator(const __tree_iterator &other) : __node_(other.__node_) {} 124 | 125 | explicit __tree_iterator(_Base_ptr __x) : __node_(__x) {} 126 | 127 | reference operator*() const FT_NOEXCEPT { 128 | return *static_cast<_Link_type>(__node_)->__valptr(); 129 | } 130 | 131 | pointer operator->() const FT_NOEXCEPT { 132 | return static_cast<_Link_type>(__node_)->__valptr(); 133 | } 134 | 135 | iterator_type &operator++() FT_NOEXCEPT { 136 | __node_ = __tree_increment(__node_); 137 | return *this; 138 | } 139 | 140 | iterator_type operator++(int) FT_NOEXCEPT { 141 | iterator_type __tmp(*this); 142 | ++(*this); 143 | return __tmp; 144 | } 145 | 146 | iterator_type &operator--() FT_NOEXCEPT { 147 | __node_ = __tree_decrement(__node_); 148 | return *this; 149 | } 150 | 151 | iterator_type operator--(int) FT_NOEXCEPT { 152 | iterator_type __tmp(*this); 153 | --(*this); 154 | return __tmp; 155 | } 156 | 157 | friend bool operator==(const iterator_type &lhs, 158 | const iterator_type &rhs) FT_NOEXCEPT { 159 | return lhs.__node_ == rhs.__node_; 160 | } 161 | friend bool operator!=(const iterator_type &lhs, 162 | const iterator_type &rhs) FT_NOEXCEPT { 163 | return lhs.__node_ != rhs.__node_; 164 | } 165 | }; 166 | 167 | template <typename _T> 168 | struct __tree_const_iterator : public iterator<bidirectional_iterator_tag, _T> { 169 | typedef _T value_type; 170 | typedef const _T *pointer; 171 | typedef const _T &reference; 172 | typedef bidirectional_iterator_tag iterator_catergory; 173 | typedef ptrdiff_t difference_type; 174 | 175 | typedef __tree_iterator<_T> iterator; 176 | typedef __tree_const_iterator<_T> const_iterator_type; 177 | typedef __tree_node_base::_Const_base_ptr _Base_ptr; 178 | typedef const __tree_node<_T> *_Link_type; 179 | 180 | _Base_ptr __node_; 181 | 182 | __tree_const_iterator() FT_NOEXCEPT : __node_() {} 183 | explicit __tree_const_iterator(_Base_ptr __x) FT_NOEXCEPT : __node_(__x) {} 184 | __tree_const_iterator(const __tree_const_iterator &other) 185 | : __node_(other.__node_) {} 186 | __tree_const_iterator(iterator __it) : __node_(__it.__node_) {} 187 | 188 | iterator __remove_const() const FT_NOEXCEPT { 189 | return iterator(const_cast<typename iterator::_Base_ptr>(__node_)); 190 | } 191 | 192 | reference operator*() const FT_NOEXCEPT { 193 | return *static_cast<_Link_type>(__node_)->__valptr(); 194 | } 195 | 196 | pointer operator->() const FT_NOEXCEPT { 197 | return static_cast<_Link_type>(__node_)->__valptr(); 198 | } 199 | 200 | const_iterator_type &operator++() FT_NOEXCEPT { 201 | __node_ = __tree_increment(__node_); 202 | return *this; 203 | } 204 | 205 | const_iterator_type operator++(int) FT_NOEXCEPT { 206 | const_iterator_type __tmp(*this); 207 | ++(*this); 208 | return __tmp; 209 | } 210 | 211 | const_iterator_type &operator--() FT_NOEXCEPT { 212 | __node_ = __tree_decrement(__node_); 213 | return *this; 214 | } 215 | 216 | const_iterator_type operator--(int) FT_NOEXCEPT { 217 | const_iterator_type __tmp(*this); 218 | --(*this); 219 | return __tmp; 220 | } 221 | 222 | friend bool operator==(const const_iterator_type &lhs, 223 | const const_iterator_type &rhs) FT_NOEXCEPT { 224 | return lhs.__node_ == rhs.__node_; 225 | } 226 | friend bool operator!=(const const_iterator_type &lhs, 227 | const const_iterator_type &rhs) FT_NOEXCEPT { 228 | return lhs.__node_ != rhs.__node_; 229 | } 230 | }; 231 | 232 | /************************************************************************************* 233 | * @brief Tree 234 | *************************************************************************************/ 235 | 236 | /** 237 | * @brief RB-tree class 238 | * 239 | * @tparam _Key: key of each node 240 | * @tparam _Val: value of each node 241 | * @tparam _KeyOfValue: get key of value functor 242 | * @tparam _Compare: Comparing functor 243 | * @tparam _Alloc: allocator (default: std::allocator<_Val>) 244 | */ 245 | template <typename _Key, typename _Val, typename _KeyOfValue, 246 | typename _Compare = std::less<_Key>, 247 | typename _Alloc = std::allocator<_Val> > 248 | class __tree { 249 | private: 250 | typedef __tree_node_base *_Base_ptr; 251 | typedef const __tree_node_base *_Const_base_ptr; 252 | typedef __tree_node<_Val> *_Link_type; 253 | typedef const __tree_node<_Val> *_Const_link_type; 254 | 255 | public: 256 | typedef _Key key_type; 257 | typedef _Val value_type; 258 | typedef value_type *pointer; 259 | typedef const value_type *const_pointer; 260 | typedef value_type &reference; 261 | typedef const value_type &const_reference; 262 | typedef size_t size_type; 263 | typedef ptrdiff_t difference_type; 264 | typedef _Alloc allocator_type; 265 | 266 | typedef typename _Alloc::template rebind<__tree_node<_Val> >::other 267 | _Node_allocator; 268 | 269 | typedef __tree_iterator<value_type> iterator; 270 | typedef __tree_const_iterator<value_type> const_iterator; 271 | typedef ft::reverse_iterator<iterator> reverse_iterator; 272 | typedef ft::reverse_iterator<const_iterator> const_reverse_iterator; 273 | 274 | private: 275 | /** 276 | * @brief impl data of tree 277 | * 278 | * @class _Node_allocator: rebind of allocator 279 | * @class __tree_key_compare: key compare functor 280 | * @class __tree_header: head of tree 281 | * 282 | */ 283 | template <typename _Key_compare> 284 | struct __tree_impl : public _Node_allocator, 285 | public __tree_key_compare<_Key_compare>, 286 | public __tree_header { 287 | typedef __tree_key_compare<_Key_compare> _Base_key_compare; 288 | 289 | __tree_impl() : _Node_allocator() {} 290 | __tree_impl(const __tree_impl &other) 291 | : _Node_allocator(other), 292 | _Base_key_compare(other.__key_comp), 293 | __tree_header() {} 294 | __tree_impl(const _Key_compare &__comp, const _Node_allocator &__a) 295 | : _Node_allocator(__a), _Base_key_compare(__comp) {} 296 | }; 297 | 298 | __tree_impl<_Compare> __impl_; 299 | 300 | _Node_allocator &__get_Node_allocator() { return this->__impl_; } 301 | const _Node_allocator &__get_Node_allocator() const { return this->__impl_; } 302 | 303 | _Link_type __allocate_node() { return __get_Node_allocator().allocate(1); } 304 | 305 | void __deallocate_node(_Link_type __p) { 306 | __get_Node_allocator().deallocate(__p, 1); 307 | } 308 | 309 | void __construct_node(_Link_type __node, const value_type &__x) { 310 | get_allocator().construct(__node->__valptr(), __x); 311 | } 312 | 313 | _Link_type __create_node(const value_type &__x) { 314 | _Link_type __tmp = __allocate_node(); 315 | __construct_node(__tmp, __x); 316 | return __tmp; 317 | } 318 | 319 | void __destroy_node(_Link_type __p) { 320 | get_allocator().destroy(__p->__valptr()); 321 | } 322 | 323 | // Return: new node which clone of __x's value and color 324 | _Link_type __clone_node(_Link_type __x) { 325 | _Link_type __tmp = this->__create_node(*__x->__valptr()); 326 | __tmp->__color_ = __x->__color_; 327 | __tmp->__left_ = NULL; 328 | __tmp->__right_ = NULL; 329 | return __tmp; 330 | } 331 | 332 | // SECTION: get specific node 333 | 334 | // SECTION: return base-node type 335 | _Base_ptr &__root() { return this->__impl_.__header_.__parent_; } 336 | _Const_base_ptr __root() const { return this->__impl_.__header_.__parent_; } 337 | 338 | _Base_ptr &__leftmost() { return this->__impl_.__header_.__left_; } 339 | _Const_base_ptr __leftmost() const { return this->__impl_.__header_.__left_; } 340 | 341 | _Base_ptr &__rightmost() { return this->__impl_.__header_.__right_; } 342 | _Const_base_ptr __rightmost() const { 343 | return this->__impl_.__header_.__right_; 344 | } 345 | 346 | _Base_ptr __end() { return &this->__impl_.__header_; } 347 | _Const_base_ptr __end() const { return &this->__impl_.__header_; } 348 | 349 | static _Base_ptr __S_minimum(_Base_ptr __x) { return __minimum(__x); } 350 | static _Const_base_ptr __S_minimum(_Const_base_ptr __x) { 351 | return __minimum(__x); 352 | } 353 | 354 | static _Base_ptr __S_maximum(_Base_ptr __x) { return __maximum(__x); } 355 | static _Const_base_ptr __S_maximum(_Const_base_ptr __x) { 356 | return __maximum(__x); 357 | } 358 | 359 | // SECTION: return key type 360 | static const _Key &__S_key(_Const_link_type __x) { 361 | return _KeyOfValue()(*__x->__valptr()); 362 | } 363 | static const _Key &__S_key(_Const_base_ptr __x) { 364 | return __S_key(static_cast<_Const_link_type>(__x)); 365 | } 366 | 367 | // SECTION: return node type 368 | _Link_type __begin() { 369 | return static_cast<_Link_type>(this->__impl_.__header_.__parent_); 370 | } 371 | _Const_link_type __begin() const { 372 | return static_cast<_Link_type>(this->__impl_.__header_.__parent_); 373 | } 374 | 375 | static _Link_type __S_left(_Base_ptr __x) { 376 | return static_cast<_Link_type>(__x->__left_); 377 | } 378 | static _Const_link_type __S_left(_Const_base_ptr __x) { 379 | return static_cast<_Link_type>(__x->__left_); 380 | } 381 | 382 | static _Link_type __S_right(_Base_ptr __x) { 383 | return static_cast<_Link_type>(__x->__right_); 384 | } 385 | static _Const_link_type __S_right(_Const_base_ptr __x) { 386 | return static_cast<_Link_type>(__x->__right_); 387 | } 388 | 389 | // SECTION: helper for public member function 390 | 391 | // get position to insert 392 | ft::pair<_Base_ptr, _Base_ptr> __get_insert_unique_pos(const key_type &__k); 393 | // get hint and get position 394 | ft::pair<_Base_ptr, _Base_ptr> __get_insert_hint_unique_pos( 395 | const_iterator __pos, const key_type &__k); 396 | 397 | _Link_type __copy_tree(_Link_type __x, _Base_ptr __p); 398 | _Link_type __copy_tree(const __tree &__t) { 399 | // copy whole tree 400 | _Link_type __root = 401 | __copy_tree(const_cast<_Link_type>(__t.__begin()), __end()); 402 | 403 | // update header 404 | __leftmost() = __S_minimum(__root); 405 | __rightmost() = __S_maximum(__root); 406 | __impl_.__node_count_ = __t.__impl_.__node_count_; 407 | return __root; 408 | } 409 | 410 | void __delete_node(_Link_type __p) { 411 | __destroy_node(__p); 412 | __deallocate_node(__p); 413 | } 414 | 415 | void __erase_without_balance(_Link_type __x); 416 | void __erase_helper(const_iterator __position); 417 | void __erase_helper(const_iterator __first, const_iterator __last); 418 | 419 | iterator __lower_bound_helper(_Link_type __x, _Base_ptr __y, 420 | const key_type &__k); 421 | const_iterator __lower_bound_helper(_Const_link_type __x, _Const_base_ptr __y, 422 | const key_type &__k) const; 423 | 424 | iterator __upper_bound_helper(_Link_type __x, _Base_ptr __y, 425 | const key_type &__k); 426 | const_iterator __upper_bound_helper(_Const_link_type __x, _Const_base_ptr __y, 427 | const key_type &__k) const; 428 | iterator __insert_helper(_Base_ptr __x, _Base_ptr __p, const value_type &__v); 429 | 430 | // SECTION: constructor/destructor 431 | public: 432 | __tree() {} 433 | __tree(const _Compare &_comp, const allocator_type &__a = allocator_type()) 434 | : __impl_(_comp, _Node_allocator(__a)) {} 435 | __tree(const __tree &other) : __impl_(other.__impl_) { 436 | if (other.__root() != NULL) __root() = __copy_tree(other); 437 | } 438 | ~__tree() { __erase_without_balance(__begin()); } 439 | 440 | __tree &operator=(const __tree &other) { 441 | if (this != &other) { 442 | this->clear(); 443 | __impl_.__key_comp = other.__impl_.__key_comp; 444 | if (other.__root() != NULL) __root() = __copy_tree(other); 445 | } 446 | return *this; 447 | } 448 | 449 | // SECTION: public member function 450 | 451 | // access to data 452 | 453 | _Compare key_comp() const { return __impl_.__key_comp; } 454 | 455 | iterator begin() { return iterator(__impl_.__header_.__left_); } 456 | const_iterator begin() const { 457 | return const_iterator(__impl_.__header_.__left_); 458 | } 459 | iterator end() { return iterator(&__impl_.__header_); } 460 | const_iterator end() const { return const_iterator(&__impl_.__header_); } 461 | reverse_iterator rbegin() { return reverse_iterator(end()); } 462 | const_reverse_iterator rbegin() const { 463 | return const_reverse_iterator(end()); 464 | } 465 | reverse_iterator rend() { return reverse_iterator(begin()); } 466 | const_reverse_iterator rend() const { 467 | return const_reverse_iterator(begin()); 468 | } 469 | 470 | // capacity 471 | bool empty() const { return __impl_.__node_count_ == 0; } 472 | size_type max_size() const { 473 | return ft::min( 474 | __get_Node_allocator().max_size(), 475 | static_cast<size_type>(std::numeric_limits<difference_type>::max())); 476 | } 477 | size_type size() const { return __impl_.__node_count_; } 478 | 479 | // modifiers 480 | 481 | void erase(iterator position) { __erase_helper(position); } 482 | void erase(const_iterator position) { __erase_helper(position); } 483 | size_type erase(const key_type &__v); 484 | void erase(iterator first, iterator last) { __erase_helper(first, last); } 485 | void erase(const_iterator first, const_iterator last) { 486 | __erase_helper(first, last); 487 | } 488 | 489 | void clear() { 490 | __erase_without_balance(__begin()); 491 | __impl_.__tree_reset(); 492 | } 493 | 494 | void swap(__tree &__t); 495 | 496 | ft::pair<iterator, bool> insert_unique(const value_type &__v); 497 | 498 | iterator insert_unique_with_hint(const_iterator __position, 499 | const value_type &__v); 500 | 501 | template <typename _InputIterator> 502 | void insert_range(_InputIterator __first, _InputIterator __last) { 503 | for (; __first != __last; ++__first) { 504 | insert_unique_with_hint(end(), *__first); 505 | } 506 | } 507 | 508 | // operations 509 | 510 | /** 511 | * @brief: find node by given key and return the node. 512 | * if not exist, return end() 513 | * 514 | * @param __k: key to find 515 | * @return iterator 516 | */ 517 | iterator find(const key_type &__k) { 518 | iterator __found = __lower_bound_helper(__begin(), __end(), __k); 519 | if (__impl_.__key_comp(__k, __S_key(__found.__node_)) || __found == end()) 520 | return end(); 521 | return __found; 522 | } 523 | const_iterator find(const key_type &__k) const { 524 | const_iterator __found = __lower_bound_helper(__begin(), __end(), __k); 525 | if (__impl_.__key_comp(__k, __S_key(__found.__node_)) || __found == end()) 526 | return end(); 527 | return __found; 528 | } 529 | 530 | size_type count(const key_type &__k) const { 531 | const_iterator __found = find(__k); 532 | return __found == end() ? 0 : 1; 533 | } 534 | 535 | iterator lower_bound(const key_type &__k) { 536 | return __lower_bound_helper(__begin(), __end(), __k); 537 | } 538 | const_iterator lower_bound(const key_type &__k) const { 539 | return __lower_bound_helper(__begin(), __end(), __k); 540 | } 541 | 542 | iterator upper_bound(const key_type &__k) { 543 | return __upper_bound_helper(__begin(), __end(), __k); 544 | } 545 | const_iterator upper_bound(const key_type &__k) const { 546 | return __upper_bound_helper(__begin(), __end(), __k); 547 | } 548 | 549 | pair<iterator, iterator> equal_range(const key_type &__k); 550 | pair<const_iterator, const_iterator> equal_range(const key_type &__k) const; 551 | 552 | allocator_type get_allocator() const { 553 | return allocator_type(__get_Node_allocator()); 554 | } 555 | 556 | // NOTE: to print tree 557 | void print_tree(); 558 | static void print_tree(const std::string &prefix, _Link_type x, bool isLeft); 559 | }; 560 | 561 | /** 562 | * @brief get unique position to insert 563 | * 564 | * @param __k: key to get position 565 | * @return ft::pair<_Base_ptr, _Base_ptr> (ret_pair) 566 | * ret_pair.first: if not NULL, insert left else insert right 567 | * ret_pair.second: if not NULL, parent of node to insert 568 | * if NULL, regard it as false which the node will not 569 | * insert 570 | */ 571 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 572 | typename _Alloc> 573 | ft::pair<typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, 574 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr> 575 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__get_insert_unique_pos( 576 | const key_type &__k) { 577 | typedef ft::pair<_Base_ptr, _Base_ptr> ret_pair; 578 | 579 | _Link_type __x = __begin(); // __root 580 | _Base_ptr __y = __end(); // __header 581 | bool __comp = true; 582 | 583 | // check left or right until meet leaf. __y gonna leaf 584 | while (__x != NULL) { 585 | __y = __x; 586 | __comp = __impl_.__key_comp(__k, __S_key(__x)); 587 | __x = __comp ? __S_left(__x) : __S_right(__x); 588 | } 589 | 590 | iterator __j = iterator(__y); 591 | if (__comp) { 592 | if (__j == begin()) // leftmost 593 | return ret_pair(__x, __y); // (NULL, leaf) 594 | --__j; // decrement node 595 | } 596 | 597 | if (__impl_.__key_comp(__S_key(__j.__node_), 598 | __k)) // compare before leaf and __k 599 | return ret_pair(__x, __y); // return (NULL, leaf) 600 | return ret_pair(__j.__node_, NULL); // return (decremented leaf, NULL(false)) 601 | } 602 | 603 | /** 604 | * @brief get unique position when hint is given 605 | * 606 | * @param __position: hint where __k should be inserted 607 | * @param __k: key to get position 608 | * @return ft::pair<_Base_ptr, _Base_ptr> (ret_pair) 609 | * ret_pair.first: if not NULL, insert left else insert right 610 | * ret_pair.second: if not NULL, parent of node to insert 611 | * if NULL, regard it as false which the node will not 612 | * insert 613 | */ 614 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 615 | typename _Alloc> 616 | ft::pair<typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, 617 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr> 618 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__get_insert_hint_unique_pos( 619 | const_iterator __position, const key_type &__k) { 620 | iterator __pos = __position.__remove_const(); 621 | typedef ft::pair<_Base_ptr, _Base_ptr> ret_pair; 622 | 623 | if (__pos.__node_ == __end()) { // header 624 | if (size() > 0 && __impl_.__key_comp(__S_key(__rightmost()), __k)) 625 | return ret_pair(NULL, __rightmost()); 626 | else 627 | return __get_insert_unique_pos(__k); 628 | } else if (__impl_.__key_comp(__k, 629 | __S_key(__pos.__node_))) { // less than pos 630 | iterator __before = __pos; 631 | 632 | if (__pos.__node_ == __leftmost()) { 633 | return ret_pair(__leftmost(), __leftmost()); 634 | } else if (__impl_.__key_comp(__S_key((--__before).__node_), __k)) { 635 | if (__S_right(__before.__node_) == NULL) 636 | return ret_pair(NULL, __before.__node_); 637 | else 638 | return ret_pair(__pos.__node_, __pos.__node_); 639 | } else { 640 | return __get_insert_unique_pos(__k); 641 | } 642 | } else if (__impl_.__key_comp(__S_key(__pos.__node_), 643 | __k)) { // greater than pos 644 | iterator __after = __pos; 645 | 646 | if (__pos.__node_ == __rightmost()) { 647 | return ret_pair(NULL, __rightmost()); 648 | } else if (__impl_.__key_comp(__k, __S_key((++__after).__node_))) { 649 | if (__S_right(__pos.__node_) == NULL) 650 | return ret_pair(NULL, __pos.__node_); 651 | else 652 | return ret_pair(__after.__node_, __after.__node_); 653 | } else { 654 | return __get_insert_unique_pos(__k); 655 | } 656 | } else // equal to pos. the key cannot be same. 657 | return ret_pair(__pos.__node_, NULL); 658 | } 659 | 660 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 661 | typename _Alloc> 662 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 663 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__insert_helper( 664 | _Base_ptr __x, _Base_ptr __p, const value_type &__v) { 665 | bool __insert_left = (__x != 0 || __p == __end() || 666 | __impl_.__key_comp(_KeyOfValue()(__v), __S_key(__p))); 667 | _Link_type __z = this->__create_node(__v); 668 | __tree_insert_and_fixup(__insert_left, __z, __p, this->__impl_.__header_); 669 | ++__impl_.__node_count_; 670 | return iterator(__z); 671 | } 672 | 673 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 674 | typename _Alloc> 675 | ft::pair<typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, 676 | bool> 677 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique( 678 | const value_type &__v) { 679 | typedef ft::pair<iterator, bool> ret_pair; 680 | ft::pair<_Base_ptr, _Base_ptr> __ret = __get_insert_unique_pos( 681 | _KeyOfValue()(__v)); // get position based key of __v 682 | 683 | if (__ret.second) { 684 | return ret_pair(__insert_helper(__ret.first, __ret.second, __v), true); 685 | } 686 | return ret_pair(iterator(__ret.first), false); 687 | } 688 | 689 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 690 | typename _Alloc> 691 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 692 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique_with_hint( 693 | const_iterator __position, const value_type &__v) { 694 | ft::pair<_Base_ptr, _Base_ptr> __ret = 695 | __get_insert_hint_unique_pos(__position, _KeyOfValue()(__v)); 696 | if (__ret.second) { 697 | return __insert_helper(__ret.first, __ret.second, __v); 698 | } 699 | return iterator(__ret.first); 700 | } 701 | 702 | /** 703 | * @brief copy tree include header of tree 704 | * 705 | * @param __x: root of new tree 706 | * @param __p: first, end() and than parent of __x 707 | * @return __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type 708 | */ 709 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 710 | typename _Alloc> 711 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type 712 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__copy_tree(_Link_type __x, 713 | _Base_ptr __p) { 714 | _Link_type __top = __clone_node(__x); // clone data of current node 715 | __top->__parent_ = __p; // link parent 716 | 717 | if (__x->__right_) { 718 | __top->__right_ = 719 | __copy_tree(__S_right(__x), __top); // copy right until NULL 720 | } 721 | __p = __top; 722 | __x = __S_left(__x); 723 | 724 | while (__x != NULL) { // copy left until NULL 725 | _Link_type __y = __clone_node(__x); 726 | __p->__left_ = __y; 727 | __y->__parent_ = __p; 728 | if (__x->__right_) { 729 | __y->__right_ = 730 | __copy_tree(__S_right(__x), __y); // if left has right, copy again 731 | } 732 | __p = __y; 733 | __x = __S_left(__x); 734 | } 735 | return __top; 736 | } 737 | 738 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 739 | typename _Alloc> 740 | void __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__erase_without_balance( 741 | _Link_type __x) { 742 | while (__x != NULL) { 743 | __erase_without_balance(__S_right(__x)); 744 | _Link_type __y = __S_left(__x); 745 | __delete_node(__x); 746 | __x = __y; 747 | } 748 | } 749 | 750 | /** 751 | * @brief helper function to erase specific node and rebalance 752 | * 753 | * @param __position 754 | */ 755 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 756 | typename _Alloc> 757 | void __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__erase_helper( 758 | const_iterator __position) { 759 | _Link_type __y = static_cast<_Link_type>(__tree_erase_and_fixup( 760 | const_cast<_Base_ptr>(__position.__node_), __impl_.__header_)); 761 | __delete_node(__y); 762 | --__impl_.__node_count_; 763 | } 764 | 765 | /** 766 | * @brief helper function to erase nodes in range and rebalance 767 | * 768 | * @param __first 769 | * @param __last 770 | */ 771 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 772 | typename _Alloc> 773 | void __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__erase_helper( 774 | const_iterator __first, const_iterator __last) { 775 | if (__first == begin() && __last == end()) 776 | clear(); 777 | else 778 | while (__first != __last) __erase_helper(__first++); 779 | } 780 | 781 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 782 | typename _Alloc> 783 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type 784 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::erase(const key_type &__v) { 785 | ft::pair<const_iterator, const_iterator> __p = equal_range(__v); 786 | const size_type __prev_size = size(); 787 | __erase_helper(__p.first, __p.second); 788 | return __prev_size - size(); 789 | } 790 | 791 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 792 | typename _Alloc> 793 | void __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::swap(__tree &__t) { 794 | if (__root() == NULL) { 795 | if (__t.__root() != NULL) __impl_.__tree_move_data(__t.__impl_); 796 | } else if (__t.__root() == NULL) 797 | __t.__impl_.__tree_move_data(__impl_); 798 | else { 799 | ft::swap(__root(), __t.__root()); 800 | ft::swap(__leftmost(), __t.__leftmost()); 801 | ft::swap(__rightmost(), __t.__rightmost()); 802 | 803 | __root()->__parent_ = __end(); 804 | __t.__root()->__parent_ = __t.__end(); 805 | ft::swap(__impl_.__node_count_, __t.__impl_.__node_count_); 806 | } 807 | ft::swap(__get_Node_allocator(), __t.__get_Node_allocator()); 808 | } 809 | 810 | /** 811 | * @brief key보다 같거나 큰 element를 리턴 812 | * 813 | * @param __x: starting node 814 | * @param __y: backup node 815 | * @param __k: key to compare 816 | * @return __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 817 | */ 818 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 819 | typename _Alloc> 820 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 821 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__lower_bound_helper( 822 | _Link_type __x, _Base_ptr __y, const key_type &__k) { 823 | while (__x != NULL) { 824 | if (!__impl_.__key_comp(__S_key(__x), __k)) { 825 | __y = __x; 826 | __x = __S_left(__x); 827 | } else { 828 | __x = __S_right(__x); 829 | } 830 | } 831 | return iterator(__y); 832 | } 833 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 834 | typename _Alloc> 835 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator 836 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__lower_bound_helper( 837 | _Const_link_type __x, _Const_base_ptr __y, const key_type &__k) const { 838 | while (__x != NULL) { 839 | if (!__impl_.__key_comp(__S_key(__x), __k)) { 840 | __y = __x; 841 | __x = __S_left(__x); 842 | } else { 843 | __x = __S_right(__x); 844 | } 845 | } 846 | return const_iterator(__y); 847 | } 848 | 849 | /** 850 | * @brief key보다 큰 element를 리턴 851 | * 852 | * @param __x: starting node 853 | * @param __y: backup node 854 | * @param __k: key to compare 855 | * @return __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 856 | */ 857 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 858 | typename _Alloc> 859 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator 860 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__upper_bound_helper( 861 | _Link_type __x, _Base_ptr __y, const key_type &__k) { 862 | while (__x != NULL) { 863 | if (__impl_.__key_comp(__k, __S_key(__x))) { 864 | __y = __x; 865 | __x = __S_left(__x); 866 | } else { 867 | __x = __S_right(__x); 868 | } 869 | } 870 | return iterator(__y); 871 | } 872 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 873 | typename _Alloc> 874 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator 875 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__upper_bound_helper( 876 | _Const_link_type __x, _Const_base_ptr __y, const key_type &__k) const { 877 | while (__x != NULL) { 878 | if (__impl_.__key_comp(__k, __S_key(__x))) { 879 | __y = __x; 880 | __x = __S_left(__x); 881 | } else { 882 | __x = __S_right(__x); 883 | } 884 | } 885 | return const_iterator(__y); 886 | } 887 | 888 | /** 889 | * @brief 컨테이너 안의 주어진 키를 포함하는 범위를 리턴. 890 | * first: >= key, second: > key. 891 | * 892 | * @param __k 893 | * @return ft::pair<iterator, iterator> 894 | */ 895 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 896 | typename _Alloc> 897 | ft::pair<typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, 898 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator> 899 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::equal_range( 900 | const key_type &__k) { 901 | _Link_type __x = __begin(); 902 | _Base_ptr __y = __end(); 903 | while (__x != NULL) { 904 | if (__impl_.__key_comp(__S_key(__x), __k)) 905 | __x = __S_right(__x); 906 | else if (__impl_.__key_comp(__k, __S_key(__x))) { 907 | __y = __x; 908 | __x = __S_left(__x); 909 | } else { // key of __x == __k 910 | _Link_type __x_up(__x); 911 | _Base_ptr __y_up(__y); 912 | __y = __x; 913 | __x = __S_left(__x); 914 | __x_up = __S_right(__x_up); 915 | return ft::pair<iterator, iterator>( 916 | __lower_bound_helper(__x, __y, __k), 917 | __upper_bound_helper(__x_up, __y_up, __k)); 918 | } 919 | } 920 | return ft::pair<iterator, iterator>(iterator(__y), iterator(__y)); 921 | } 922 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 923 | typename _Alloc> 924 | ft::pair< 925 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, 926 | typename __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator> 927 | __tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::equal_range( 928 | const key_type &__k) const { 929 | _Const_link_type __x = __begin(); 930 | _Const_base_ptr __y = __end(); 931 | while (__x != NULL) { 932 | if (__impl_.__key_comp(__S_key(__x), __k)) 933 | __x = __S_right(__x); 934 | else if (__impl_.__key_comp(__k, __S_key(__x))) { 935 | __y = __x; 936 | __x = __S_left(__x); 937 | } else { // key of __x == __k 938 | _Const_link_type __x_up(__x); 939 | _Const_base_ptr __y_up(__y); 940 | __y = __x; 941 | __x = __S_left(__x); 942 | __x_up = __S_right(__x_up); 943 | return ft::pair<const_iterator, const_iterator>( 944 | __lower_bound_helper(__x, __y, __k), 945 | __upper_bound_helper(__x_up, __y_up, __k)); 946 | } 947 | } 948 | return ft::pair<const_iterator, const_iterator>(const_iterator(__y), 949 | const_iterator(__y)); 950 | } 951 | 952 | } // namespace ft 953 | 954 | #endif // __TREE 955 | -------------------------------------------------------------------------------- /include/algorithm.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file algorithm.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief my STL algorithms 5 | * @version 0.1 6 | * @date 2022-04-09 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef ALGORITHMS_HPP 13 | #define ALGORITHMS_HPP 14 | 15 | namespace ft { 16 | template <typename InputIterator1, typename InputIterator2> 17 | bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) { 18 | while (first1 != last1) { 19 | if (!(*first1 == *first2)) return false; 20 | ++first1, ++first2; 21 | } 22 | return true; 23 | } 24 | 25 | template <typename InputIterator1, typename InputIterator2, 26 | typename BinaryPredicate> 27 | bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, 28 | BinaryPredicate pred) { 29 | while (first1 != last1) { 30 | if (!pred(*first1, *first2)) return false; 31 | ++first1, ++first2; 32 | } 33 | return true; 34 | } 35 | 36 | template <typename InputIterator1, typename InputIterator2> 37 | bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, 38 | InputIterator2 first2, InputIterator2 last2) { 39 | while (first1 != last1) { 40 | if (first2 == last2 || *first2 < *first1) 41 | return false; 42 | else if (*first1 < *first2) 43 | return true; 44 | ++first1, ++first2; 45 | } 46 | return (first2 != last2); 47 | } 48 | 49 | template <typename InputIterator1, typename InputIterator2, typename Compare> 50 | bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, 51 | InputIterator2 first2, InputIterator2 last2, 52 | Compare Comp) { 53 | while (first1 != last1) { 54 | if (first2 == last2 || Comp(*first2, *first1)) 55 | return false; 56 | else if (Comp(*first1, *first2)) 57 | return true; 58 | ++first1, ++first2; 59 | } 60 | return (first2 != last2); 61 | } 62 | 63 | template <typename T> 64 | const T& min(const T& x, const T& y) { 65 | return (x < y) ? x : y; 66 | } 67 | } // namespace ft 68 | 69 | #endif // ALGORITHMS_HPP 70 | -------------------------------------------------------------------------------- /include/iterator.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file iterator.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief iterator_traits and reverse_iterator 5 | * @version 0.1 6 | * @date 2022-03-31 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef ITERATOR 13 | #define ITERATOR 14 | 15 | #include <cstddef> 16 | #include <iterator> 17 | 18 | #include "type_traits.hpp" 19 | 20 | namespace ft { 21 | 22 | // tags for iterator_traits 23 | #if defined(_LIBCPP_ITERATOR) || defined(_STL_ITERATOR_H) 24 | 25 | typedef std::input_iterator_tag input_iterator_tag; 26 | typedef std::output_iterator_tag output_iterator_tag; 27 | typedef std::forward_iterator_tag forward_iterator_tag; 28 | typedef std::bidirectional_iterator_tag bidirectional_iterator_tag; 29 | typedef std::random_access_iterator_tag random_access_iterator_tag; 30 | 31 | #else // !defined(_LIBCPP_ITERATOR) && !defined(_STL_ITERATOR_H) 32 | 33 | struct input_iterator_tag {}; 34 | struct output_iterator_tag {}; 35 | struct forward_iterator_tag : input_iterator_tag {}; 36 | struct bidirectional_iterator_tag : forward_iterator_tag {}; 37 | struct random_access_iterator_tag : bidirectional_iterator_tag {}; 38 | 39 | #endif // defined(_LIBCPP_ITERATOR) || defined(_STL_ITERATOR_H) 40 | 41 | /** 42 | * @brief base of iterator. common to %iterator classes. 43 | * 44 | * @tparam _Category 45 | * @tparam _T 46 | * @tparam _Distance 47 | * @tparam _pointer 48 | * @tparam _reference 49 | */ 50 | template <typename _Category, typename _T, typename _Distance = ptrdiff_t, 51 | typename _pointer = _T *, typename _reference = _T &> 52 | struct iterator { 53 | typedef _T value_type; 54 | typedef _Distance difference_type; 55 | typedef _pointer pointer; 56 | typedef _reference reference; 57 | typedef _Category iterator_category; 58 | }; 59 | 60 | // iterator_traits 61 | 62 | template <typename _T> 63 | struct __has_iterator_typedefs { 64 | private: 65 | struct __two { 66 | char __x; 67 | char __y; 68 | }; 69 | template <typename _U> 70 | static __two __test(...){}; 71 | template <typename _U> 72 | static char __test( 73 | typename ft::void_t<typename _U::iterator_category>::type * = 0, 74 | typename ft::void_t<typename _U::difference_type>::type * = 0, 75 | typename ft::void_t<typename _U::value_type>::type * = 0, 76 | typename ft::void_t<typename _U::reference>::type * = 0, 77 | typename ft::void_t<typename _U::pointer>::type * = 0){}; 78 | 79 | public: 80 | static const bool value = sizeof(__test<_T>(0, 0, 0, 0, 0)) == 1; 81 | }; 82 | 83 | template <typename _Iter, bool> 84 | struct __iterator_traits_typedefs {}; 85 | 86 | template <typename _Iter> 87 | struct __iterator_traits_typedefs<_Iter, true> { 88 | typedef typename _Iter::iterator_category iterator_category; 89 | typedef typename _Iter::value_type value_type; 90 | typedef typename _Iter::difference_type difference_type; 91 | typedef typename _Iter::pointer pointer; 92 | typedef typename _Iter::reference reference; 93 | }; 94 | 95 | template <typename _Iter, bool> 96 | struct __iterator_traits {}; 97 | 98 | template <typename _Iter> 99 | struct __iterator_traits<_Iter, true> 100 | : __iterator_traits_typedefs< 101 | _Iter, is_same<typename _Iter::iterator_category, 102 | input_iterator_tag>::value || 103 | is_same<typename _Iter::iterator_category, 104 | output_iterator_tag>::value || 105 | is_same<typename _Iter::iterator_category, 106 | forward_iterator_tag>::value || 107 | is_same<typename _Iter::iterator_category, 108 | bidirectional_iterator_tag>::value || 109 | is_same<typename _Iter::iterator_category, 110 | random_access_iterator_tag>::value> {}; 111 | 112 | template <typename _Iter> 113 | struct iterator_traits 114 | : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {}; 115 | 116 | // iterator_traits specialization for pointer type 117 | template <typename _T> 118 | struct iterator_traits<_T *> { 119 | typedef random_access_iterator_tag iterator_category; 120 | typedef _T value_type; 121 | typedef ptrdiff_t difference_type; 122 | typedef _T *pointer; 123 | typedef _T &reference; 124 | }; 125 | 126 | // iterator_traits specialization for const pointer type 127 | template <typename _T> 128 | struct iterator_traits<const _T *> { 129 | typedef random_access_iterator_tag iterator_category; 130 | typedef typename remove_cv<_T>::type value_type; 131 | typedef ptrdiff_t difference_type; 132 | typedef const _T *pointer; 133 | typedef const _T &reference; 134 | }; 135 | 136 | template <typename _Iter, 137 | bool = __has_iterator_typedefs<iterator_traits<_Iter> >::value> 138 | struct __is_iterator : public false_type { 139 | typedef void category; 140 | }; 141 | 142 | template <typename _Iter> 143 | struct __is_iterator<_Iter, true> : public true_type { 144 | typedef typename _Iter::iterator_category category; 145 | }; 146 | 147 | template <typename _T> 148 | struct __is_iterator<_T *, true> : public true_type { 149 | typedef typename iterator_traits<_T *>::iterator_category category; 150 | }; 151 | 152 | template <typename _Iter> 153 | struct __is_input_iterator 154 | : public integral_constant<bool, 155 | (is_same<typename __is_iterator<_Iter>::category, 156 | input_iterator_tag>::value || 157 | is_same<typename __is_iterator<_Iter>::category, 158 | forward_iterator_tag>::value || 159 | is_same<typename __is_iterator<_Iter>::category, 160 | bidirectional_iterator_tag>::value || 161 | is_same<typename __is_iterator<_Iter>::category, 162 | random_access_iterator_tag>::value)> {}; 163 | 164 | template <typename _Iter> 165 | struct __is_output_iterator 166 | : public integral_constant<bool, 167 | is_same<typename __is_iterator<_Iter>::category, 168 | output_iterator_tag>::value> {}; 169 | 170 | template <typename _Iter> 171 | struct __is_forward_iterator 172 | : public integral_constant< 173 | bool, is_same<typename __is_iterator<_Iter>::category, 174 | forward_iterator_tag>::value || 175 | is_same<typename __is_iterator<_Iter>::category, 176 | bidirectional_iterator_tag>::value || 177 | is_same<typename __is_iterator<_Iter>::category, 178 | random_access_iterator_tag>::value> {}; 179 | 180 | template <typename _Iter> 181 | struct __is_bidirectional_iterator 182 | : public integral_constant< 183 | bool, is_same<typename __is_iterator<_Iter>::category, 184 | bidirectional_iterator_tag>::value || 185 | is_same<typename __is_iterator<_Iter>::category, 186 | random_access_iterator_tag>::value> {}; 187 | 188 | template <typename _Iter> 189 | struct __is_random_access_iterator 190 | : public integral_constant<bool, 191 | is_same<typename __is_iterator<_Iter>::category, 192 | random_access_iterator_tag>::value> {}; 193 | 194 | template <typename _Iter> 195 | class reverse_iterator 196 | : public iterator<typename iterator_traits<_Iter>::iterator_category, 197 | typename iterator_traits<_Iter>::value_type, 198 | typename iterator_traits<_Iter>::difference_type, 199 | typename iterator_traits<_Iter>::pointer, 200 | typename iterator_traits<_Iter>::reference> { 201 | protected: 202 | _Iter current; 203 | 204 | public: 205 | // typedef 206 | typedef _Iter iterator_type; 207 | typedef typename iterator_traits<_Iter>::value_type value_type; 208 | typedef typename iterator_traits<_Iter>::difference_type difference_type; 209 | typedef typename iterator_traits<_Iter>::reference reference; 210 | typedef typename iterator_traits<_Iter>::pointer pointer; 211 | 212 | // constructor 213 | reverse_iterator() : current() {} 214 | reverse_iterator(_Iter __it) : current(__it) {} 215 | template <typename _U> 216 | reverse_iterator(const reverse_iterator<_U> &__u) : current(__u.base()) {} 217 | template <typename _U> 218 | reverse_iterator &operator=(const reverse_iterator<_U> &__u) { 219 | current = __u.base(); 220 | return *this; 221 | } 222 | 223 | _Iter base() const { return current; } 224 | 225 | // operator 226 | reference operator*() const { 227 | _Iter __tmp = current; 228 | return *--__tmp; 229 | } 230 | pointer operator->() const { return &(operator*()); } 231 | reverse_iterator &operator++() { 232 | --current; 233 | return *this; 234 | } 235 | reverse_iterator operator++(int) { 236 | reverse_iterator __tmp(*this); 237 | --current; 238 | return __tmp; 239 | } 240 | reverse_iterator &operator--() { 241 | ++current; 242 | return *this; 243 | } 244 | reverse_iterator operator--(int) { 245 | reverse_iterator __tmp(*this); 246 | ++current; 247 | return __tmp; 248 | } 249 | reverse_iterator operator+(difference_type __n) const { 250 | return reverse_iterator(current - __n); 251 | } 252 | reverse_iterator operator-(difference_type __n) const { 253 | return reverse_iterator(current + __n); 254 | } 255 | reverse_iterator &operator+=(difference_type __n) { 256 | current -= __n; 257 | return *this; 258 | } 259 | reverse_iterator &operator-=(difference_type __n) { 260 | current += __n; 261 | return *this; 262 | } 263 | reference operator[](difference_type __n) const { return *(*this + __n); } 264 | }; 265 | 266 | // non-member function overloads 267 | 268 | template <typename _Iter1, typename _Iter2> 269 | bool operator==(const reverse_iterator<_Iter1> &__lhs, 270 | const reverse_iterator<_Iter2> &__rhs) { 271 | return __lhs.base() == __rhs.base(); 272 | } 273 | 274 | template <typename _Iter1, typename _Iter2> 275 | bool operator!=(const reverse_iterator<_Iter1> &__lhs, 276 | const reverse_iterator<_Iter2> &__rhs) { 277 | return __lhs.base() != __rhs.base(); 278 | } 279 | 280 | template <typename _Iter1, typename _Iter2> 281 | bool operator<(const reverse_iterator<_Iter1> &__lhs, 282 | const reverse_iterator<_Iter2> &__rhs) { 283 | return __lhs.base() > __rhs.base(); 284 | } 285 | 286 | template <typename _Iter1, typename _Iter2> 287 | bool operator>(const reverse_iterator<_Iter1> &__lhs, 288 | const reverse_iterator<_Iter2> &__rhs) { 289 | return __lhs.base() < __rhs.base(); 290 | } 291 | 292 | template <typename _Iter1, typename _Iter2> 293 | bool operator>=(const reverse_iterator<_Iter1> &__lhs, 294 | const reverse_iterator<_Iter2> &__rhs) { 295 | return __lhs.base() <= __rhs.base(); 296 | } 297 | 298 | template <typename _Iter1, typename _Iter2> 299 | bool operator<=(const reverse_iterator<_Iter1> &__lhs, 300 | const reverse_iterator<_Iter2> &__rhs) { 301 | return __lhs.base() >= __rhs.base(); 302 | } 303 | 304 | template <typename _Iter1, typename _Iter2> 305 | typename reverse_iterator<_Iter1>::difference_type operator-( 306 | const reverse_iterator<_Iter1> &__lhs, 307 | const reverse_iterator<_Iter2> &__rhs) { 308 | return __rhs.base() - __lhs.base(); 309 | } 310 | 311 | template <typename _Iter> 312 | reverse_iterator<_Iter> operator+( 313 | typename reverse_iterator<_Iter>::difference_type __n, 314 | const reverse_iterator<_Iter> &__it) { 315 | return reverse_iterator<_Iter>(__it.base() - __n); 316 | } 317 | 318 | template <typename _InputIterator> 319 | inline typename iterator_traits<_InputIterator>::difference_type __distance( 320 | _InputIterator __first, _InputIterator __last, ft::input_iterator_tag) { 321 | typename iterator_traits<_InputIterator>::difference_type d(0); 322 | for (; __first != __last; ++__first) ++d; 323 | return d; 324 | } 325 | 326 | template <typename _RandIterator> 327 | inline typename iterator_traits<_RandIterator>::difference_type __distance( 328 | _RandIterator __first, _RandIterator __last, 329 | ft::random_access_iterator_tag) { 330 | return __last - __first; 331 | } 332 | 333 | template <typename _InputIterator> 334 | inline typename iterator_traits<_InputIterator>::difference_type distance( 335 | _InputIterator first, _InputIterator last) { 336 | return ft::__distance( 337 | first, last, 338 | typename iterator_traits<_InputIterator>::iterator_category()); 339 | } 340 | 341 | } // namespace ft 342 | 343 | #endif // ITERATOR 344 | -------------------------------------------------------------------------------- /include/map.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file map.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief stl map 5 | * @version 0.1 6 | * @date 2022-04-12 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef MAP_HPP 13 | #define MAP_HPP 14 | 15 | #include <functional> 16 | 17 | #include "__tree.hpp" 18 | #include "algorithm.hpp" 19 | #include "iterator.hpp" 20 | #include "utility.hpp" 21 | 22 | namespace ft { 23 | 24 | template <typename _Key, typename _T, typename _Compare = std::less<_Key>, 25 | typename _Alloc = std::allocator<ft::pair<const _Key, _T> > > 26 | class map { 27 | // SECTION: type define 28 | public: 29 | typedef _Key key_type; 30 | typedef _T mapped_type; 31 | typedef _Compare key_compare; 32 | typedef _Alloc allocator_type; 33 | typedef ft::pair<const key_type, mapped_type> value_type; 34 | 35 | private: 36 | typedef __tree<key_type, value_type, ft::select_first<value_type>, 37 | key_compare, allocator_type> 38 | __base; 39 | 40 | public: 41 | typedef typename allocator_type::reference reference; 42 | typedef typename allocator_type::const_reference const_reference; 43 | typedef typename allocator_type::pointer pointer; 44 | typedef typename allocator_type::const_pointer const_pointer; 45 | 46 | typedef typename __base::iterator iterator; 47 | typedef typename __base::const_iterator const_iterator; 48 | typedef typename __base::reverse_iterator reverse_iterator; 49 | typedef typename __base::const_reverse_iterator const_reverse_iterator; 50 | typedef typename __base::difference_type difference_type; 51 | typedef typename __base::size_type size_type; 52 | 53 | class value_compare 54 | : public std::binary_function<value_type, value_type, bool> { 55 | friend class map<_Key, _T, _Compare, _Alloc>; 56 | 57 | protected: 58 | _Compare comp; 59 | value_compare(_Compare c) : comp(c) {} 60 | 61 | public: 62 | bool operator()(const value_type& x, const value_type& y) const { 63 | return comp(x.first, y.first); 64 | } 65 | }; 66 | 67 | private: 68 | // base of map 69 | __base __tree_; 70 | 71 | public: 72 | // SECTION: constructor 73 | explicit map(const key_compare& comp = key_compare(), 74 | const allocator_type& alloc = allocator_type()) 75 | : __tree_(comp, alloc) {} 76 | 77 | template <typename _InputIterator> 78 | map(_InputIterator first, _InputIterator last, 79 | const key_compare& comp = key_compare(), 80 | const allocator_type& alloc = allocator_type()) 81 | : __tree_(comp, alloc) { 82 | __tree_.insert_range(first, last); 83 | } 84 | 85 | map(const map& other) : __tree_(other.__tree_) {} 86 | 87 | map& operator=(const map& other) { 88 | if (this != &other) { 89 | __tree_ = other.__tree_; 90 | } 91 | return *this; 92 | } 93 | 94 | ~map() {} 95 | 96 | // SECTION: public member function 97 | 98 | // iterators 99 | iterator begin() FT_NOEXCEPT { return iterator(__tree_.begin()); } 100 | const_iterator begin() const FT_NOEXCEPT { 101 | return const_iterator(__tree_.begin()); 102 | } 103 | iterator end() FT_NOEXCEPT { return iterator(__tree_.end()); } 104 | const_iterator end() const FT_NOEXCEPT { 105 | return const_iterator(__tree_.end()); 106 | } 107 | reverse_iterator rbegin() FT_NOEXCEPT { return __tree_.rbegin(); } 108 | const_reverse_iterator rbegin() const FT_NOEXCEPT { return __tree_.rbegin(); } 109 | reverse_iterator rend() FT_NOEXCEPT { return __tree_.rend(); } 110 | const_reverse_iterator rend() const FT_NOEXCEPT { return __tree_.rend(); } 111 | 112 | // capacity 113 | bool empty() const FT_NOEXCEPT { return __tree_.empty(); } 114 | size_type size() const FT_NOEXCEPT { return __tree_.size(); } 115 | size_type max_size() const FT_NOEXCEPT { return __tree_.max_size(); } 116 | 117 | // element access 118 | mapped_type& operator[](const key_type& k) { 119 | iterator __it = lower_bound(k); 120 | 121 | if (__it == end() || key_compare()(k, (*__it).first)) 122 | __it = insert(__it, value_type(k, mapped_type())); 123 | return (*__it).second; 124 | } 125 | 126 | mapped_type& at(const key_type& k) { 127 | iterator __it = lower_bound(k); 128 | 129 | if (__it == end() || key_compare()(k, (*__it).first)) 130 | throw std::out_of_range("map: out of range"); 131 | return (*__it).second; 132 | } 133 | 134 | const mapped_type& at(const key_type& k) const { 135 | iterator __it = lower_bound(k); 136 | 137 | if (__it == end() || key_compare()(k, (*__it).first)) 138 | throw std::out_of_range("map: out of range"); 139 | return (*__it).second; 140 | } 141 | 142 | // modifiers 143 | pair<iterator, bool> insert(const value_type& val) { 144 | return __tree_.insert_unique(val); 145 | } 146 | iterator insert(iterator position, const value_type& val) { 147 | return __tree_.insert_unique_with_hint(position, val); 148 | } 149 | template <typename _InputIterator> 150 | void insert(_InputIterator first, _InputIterator last) { 151 | __tree_.insert_range(first, last); 152 | } 153 | 154 | void erase(iterator position) { __tree_.erase(position); } 155 | size_type erase(const key_type& k) { return __tree_.erase(k); } 156 | void erase(iterator first, iterator last) { __tree_.erase(first, last); } 157 | 158 | void swap(map& other) { __tree_.swap(other.__tree_); } 159 | 160 | void clear() { __tree_.clear(); } 161 | 162 | // observers 163 | key_compare key_comp() const { return __tree_.key_comp(); } 164 | value_compare value_comp() const { return value_compare(__tree_.key_comp()); } 165 | 166 | // operations 167 | iterator find(const key_type& k) { return __tree_.find(k); } 168 | const_iterator find(const key_type& k) const { return __tree_.find(k); } 169 | 170 | size_type count(const key_type& k) const { return __tree_.count(k); } 171 | 172 | iterator lower_bound(const key_type& k) { return __tree_.lower_bound(k); } 173 | const_iterator lower_bound(const key_type& k) const { 174 | return __tree_.lower_bound(k); 175 | } 176 | 177 | iterator upper_bound(const key_type& k) { return __tree_.upper_bound(k); } 178 | const_iterator upper_bound(const key_type& k) const { 179 | return __tree_.upper_bound(k); 180 | } 181 | 182 | pair<const_iterator, const_iterator> equal_range(const key_type& k) const { 183 | return __tree_.equal_range(k); 184 | } 185 | pair<iterator, iterator> equal_range(const key_type& k) { 186 | return __tree_.equal_range(k); 187 | } 188 | 189 | allocator_type get_allocator() const { 190 | return allocator_type(__tree_.get_allocator()); 191 | } 192 | 193 | // template <typename _K1, typename _T1, typename _C1, typename _A1> 194 | // friend bool operator==(const map& lhs, const map& rhs); 195 | // template <typename _K1, typename _T1, typename _C1, typename _A1> 196 | // friend bool operator<(const map& lhs, const map& rhs); 197 | }; 198 | 199 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 200 | bool operator==(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 201 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 202 | return (lhs.size() == rhs.size() && 203 | ft::equal(lhs.begin(), lhs.end(), rhs.begin())); 204 | } 205 | 206 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 207 | bool operator!=(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 208 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 209 | return !(lhs == rhs); 210 | } 211 | 212 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 213 | bool operator<(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 214 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 215 | return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), 216 | rhs.end()); 217 | } 218 | 219 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 220 | bool operator>(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 221 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 222 | return rhs < lhs; 223 | } 224 | 225 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 226 | bool operator<=(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 227 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 228 | return !(rhs < lhs); 229 | } 230 | 231 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 232 | bool operator>=(const ft::map<_Key, _T, _Compare, _Alloc>& lhs, 233 | const ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 234 | return !(lhs < rhs); 235 | } 236 | 237 | template <typename _Key, typename _T, typename _Compare, typename _Alloc> 238 | void swap(ft::map<_Key, _T, _Compare, _Alloc>& lhs, 239 | ft::map<_Key, _T, _Compare, _Alloc>& rhs) { 240 | lhs.swap(rhs); 241 | } 242 | 243 | } // namespace ft 244 | 245 | #endif // MAP_HPP -------------------------------------------------------------------------------- /include/set.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file set.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief stl set 5 | * @version 0.1 6 | * @date 2022-04-19 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef SET_HPP 13 | #define SET_HPP 14 | 15 | #include "__tree.hpp" 16 | #include "algorithm.hpp" 17 | #include "iterator.hpp" 18 | 19 | namespace ft { 20 | template <typename _T, typename _Compare = std::less<_T>, 21 | typename _Alloc = std::allocator<_T> > 22 | class set { 23 | // SECTION: type define 24 | public: 25 | typedef _T key_type; 26 | typedef _T value_type; 27 | typedef _Compare key_compare; 28 | typedef _Compare value_compare; 29 | typedef _Alloc allocator_type; 30 | typedef typename allocator_type::reference reference; 31 | typedef typename allocator_type::const_reference const_reference; 32 | typedef typename allocator_type::pointer pointer; 33 | typedef typename allocator_type::const_pointer const_pointer; 34 | 35 | private: 36 | typedef __tree<_T, _T, ft::identity<_T>, key_compare, allocator_type> __base; 37 | 38 | public: 39 | typedef typename __base::const_iterator iterator; 40 | typedef typename __base::const_iterator const_iterator; 41 | typedef typename __base::const_reverse_iterator reverse_iterator; 42 | typedef typename __base::const_reverse_iterator const_reverse_iterator; 43 | typedef typename __base::difference_type difference_type; 44 | typedef typename __base::size_type size_type; 45 | 46 | private: 47 | // SECTION: base of set 48 | __base __tree_; 49 | 50 | // SECTION: public member function 51 | public: 52 | // constructor 53 | explicit set(const key_compare& comp = key_compare(), 54 | const allocator_type& alloc = allocator_type()) 55 | : __tree_(comp, alloc) {} 56 | 57 | template <typename _InputIterator> 58 | set(_InputIterator first, _InputIterator last, 59 | const key_compare& comp = key_compare(), 60 | const allocator_type& alloc = allocator_type()) 61 | : __tree_(comp, alloc) { 62 | __tree_.insert_range(first, last); 63 | } 64 | 65 | set(const set& other) : __tree_(other.__tree_) {} 66 | 67 | set& operator=(const set& other) { 68 | if (this != &other) { 69 | __tree_ = other.__tree_; 70 | } 71 | return *this; 72 | } 73 | 74 | ~set() {} 75 | 76 | // iterators 77 | iterator begin() FT_NOEXCEPT { return iterator(__tree_.begin()); } 78 | const_iterator begin() const FT_NOEXCEPT { 79 | return const_iterator(__tree_.begin()); 80 | } 81 | iterator end() FT_NOEXCEPT { return iterator(__tree_.end()); } 82 | const_iterator end() const FT_NOEXCEPT { 83 | return const_iterator(__tree_.end()); 84 | } 85 | reverse_iterator rbegin() FT_NOEXCEPT { return __tree_.rbegin(); } 86 | const_reverse_iterator rbegin() const FT_NOEXCEPT { return __tree_.rbegin(); } 87 | reverse_iterator rend() FT_NOEXCEPT { return __tree_.rend(); } 88 | const_reverse_iterator rend() const FT_NOEXCEPT { return __tree_.rend(); } 89 | 90 | // capacity 91 | bool empty() const FT_NOEXCEPT { return __tree_.empty(); } 92 | size_type size() const FT_NOEXCEPT { return __tree_.size(); } 93 | size_type max_size() const FT_NOEXCEPT { return __tree_.max_size(); } 94 | 95 | // modifiers 96 | pair<iterator, bool> insert(const value_type& val) { 97 | return __tree_.insert_unique(val); 98 | } 99 | iterator insert(iterator position, const value_type& val) { 100 | return __tree_.insert_unique_with_hint(position, val); 101 | } 102 | template <typename _InputIterator> 103 | void insert(_InputIterator first, _InputIterator last) { 104 | __tree_.insert_range(first, last); 105 | } 106 | 107 | void erase(iterator position) { __tree_.erase(position); } 108 | size_type erase(const key_type& k) { return __tree_.erase(k); } 109 | void erase(iterator first, iterator last) { __tree_.erase(first, last); } 110 | 111 | void swap(set& other) { __tree_.swap(other.__tree_); } 112 | 113 | void clear() { __tree_.clear(); } 114 | 115 | // observers 116 | key_compare key_comp() const { return __tree_.key_comp(); } 117 | value_compare value_comp() const { return value_compare(__tree_.key_comp()); } 118 | 119 | // operations 120 | iterator find(const value_type& k) const { 121 | return __tree_.find(k).__remove_const(); 122 | } 123 | size_type count(const value_type& k) const { return __tree_.count(k); } 124 | iterator lower_bound(const value_type& k) { return __tree_.lower_bound(k); } 125 | const_iterator lower_bound(const value_type& k) const { 126 | return __tree_.lower_bound(k); 127 | } 128 | iterator upper_bound(const value_type& k) { return __tree_.upper_bound(k); } 129 | const_iterator upper_bound(const value_type& k) const { 130 | return __tree_.upper_bound(k); 131 | } 132 | pair<iterator, iterator> equal_range(const value_type& k) { 133 | return __tree_.equal_range(k); 134 | } 135 | pair<const_iterator, const_iterator> equal_range(const value_type& k) const { 136 | return __tree_.equal_range(k); 137 | } 138 | allocator_type get_allocator() const { 139 | return allocator_type(__tree_.get_allocator()); 140 | } 141 | template <typename _T1, typename _C1, typename _A1> 142 | friend bool operator==(const set& lhs, const set& rhs); 143 | template <typename _T1, typename _C1, typename _A1> 144 | friend bool operator<(const set& lhs, const set& rhs); 145 | }; 146 | 147 | template <typename _T, typename _Compare, typename _Alloc> 148 | bool operator==(const ft::set<_T, _Compare, _Alloc>& lhs, 149 | const ft::set<_T, _Compare, _Alloc>& rhs) { 150 | return (lhs.size() == rhs.size() && 151 | ft::equal(lhs.begin(), lhs.end(), rhs.begin())); 152 | } 153 | 154 | template <typename _T, typename _Compare, typename _Alloc> 155 | bool operator!=(const ft::set<_T, _Compare, _Alloc>& lhs, 156 | const ft::set<_T, _Compare, _Alloc>& rhs) { 157 | return !(lhs == rhs); 158 | } 159 | 160 | template <typename _T, typename _Compare, typename _Alloc> 161 | bool operator<(const ft::set<_T, _Compare, _Alloc>& lhs, 162 | const ft::set<_T, _Compare, _Alloc>& rhs) { 163 | return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), 164 | rhs.end()); 165 | } 166 | 167 | template <typename _T, typename _Compare, typename _Alloc> 168 | bool operator>(const ft::set<_T, _Compare, _Alloc>& lhs, 169 | const ft::set<_T, _Compare, _Alloc>& rhs) { 170 | return rhs < lhs; 171 | } 172 | 173 | template <typename _T, typename _Compare, typename _Alloc> 174 | bool operator<=(const ft::set<_T, _Compare, _Alloc>& lhs, 175 | const ft::set<_T, _Compare, _Alloc>& rhs) { 176 | return !(rhs < lhs); 177 | } 178 | 179 | template <typename _T, typename _Compare, typename _Alloc> 180 | bool operator>=(const ft::set<_T, _Compare, _Alloc>& lhs, 181 | const ft::set<_T, _Compare, _Alloc>& rhs) { 182 | return !(lhs < rhs); 183 | } 184 | 185 | template <typename _T, typename _Compare, typename _Alloc> 186 | void swap(ft::set<_T, _Compare, _Alloc>& lhs, 187 | ft::set<_T, _Compare, _Alloc>& rhs) { 188 | lhs.swap(rhs); 189 | } 190 | 191 | } // namespace ft 192 | 193 | #endif // SET_HPP -------------------------------------------------------------------------------- /include/stack.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file stack.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief stack container 5 | * @version 0.1 6 | * @date 2022-04-10 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef STACK_HPP 13 | #define STACK_HPP 14 | 15 | #include "vector.hpp" 16 | #define FT_NOEXCEPT throw() 17 | 18 | namespace ft { 19 | 20 | template <typename _T, typename _Container = vector<_T> > 21 | class stack { 22 | public: 23 | typedef _Container container_type; 24 | typedef typename container_type::value_type value_type; 25 | typedef typename container_type::size_type size_type; 26 | 27 | protected: 28 | container_type c; 29 | 30 | public: 31 | // constructor 32 | explicit stack(const container_type& __c = container_type()) : c(__c) {} 33 | 34 | // member function 35 | bool empty() const { return c.empty(); } 36 | size_type size() const { return c.size(); } 37 | value_type& top() { return c.back(); } 38 | const value_type& top() const { return c.back(); } 39 | void push(const value_type& val) { return c.push_back(val); } 40 | void pop() { c.pop_back(); } 41 | 42 | // relational operator 43 | // Use friend to compare protected member variable 44 | template <typename T, typename C> 45 | friend bool operator==(const stack<T, C>& lhs, const stack<T, C>& rhs); 46 | template <typename T, typename C> 47 | friend bool operator<(const stack<T, C>& lhs, const stack<T, C>& rhs); 48 | }; 49 | 50 | template <typename T, typename C> 51 | inline bool operator==(const stack<T, C>& lhs, const stack<T, C>& rhs) { 52 | return lhs.c == rhs.c; 53 | } 54 | 55 | template <typename T, typename C> 56 | inline bool operator!=(const stack<T, C>& lhs, const stack<T, C>& rhs) { 57 | return !(lhs == rhs); 58 | } 59 | 60 | template <typename T, typename C> 61 | inline bool operator<(const stack<T, C>& lhs, const stack<T, C>& rhs) { 62 | return lhs.c < rhs.c; 63 | } 64 | 65 | template <typename T, typename C> 66 | inline bool operator<=(const stack<T, C>& lhs, const stack<T, C>& rhs) { 67 | return !(rhs < lhs); 68 | } 69 | 70 | template <typename T, typename C> 71 | inline bool operator>(const stack<T, C>& lhs, const stack<T, C>& rhs) { 72 | return rhs < lhs; 73 | } 74 | 75 | template <typename T, typename C> 76 | inline bool operator>=(const stack<T, C>& lhs, const stack<T, C>& rhs) { 77 | return !(lhs < rhs); 78 | } 79 | 80 | } // namespace ft 81 | 82 | #endif // STACK_HPP -------------------------------------------------------------------------------- /include/test.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief commom header for test 5 | * @version 0.1 6 | * @date 2022-04-09 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef TEST_HPP 13 | #define TEST_HPP 14 | 15 | #include <sys/time.h> 16 | 17 | #include <__tree> 18 | #include <cstdlib> 19 | #include <iostream> 20 | #include <iterator> 21 | #include <map> 22 | #include <memory> 23 | #include <set> 24 | #include <stack> 25 | #include <string> 26 | #include <type_traits> 27 | #include <utility> 28 | #include <vector> 29 | 30 | #include "__tree.hpp" 31 | #include "iterator.hpp" 32 | #include "map.hpp" 33 | #include "set.hpp" 34 | #include "stack.hpp" 35 | #include "type_traits.hpp" 36 | #include "utility.hpp" 37 | #include "vector.hpp" 38 | 39 | #define L_CYAN "\033[1;96m" 40 | #define RESET "\033[0m" 41 | #define PRINT(...) std::cout, L_CYAN, __VA_ARGS__, RESET, "\n" 42 | 43 | template <typename T> 44 | std::ostream& operator,(std::ostream& out, const T& t) { 45 | out << t; 46 | return out; 47 | } 48 | 49 | #endif // TEST_HPP 50 | -------------------------------------------------------------------------------- /include/type_traits.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file type_traits.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief enable_if and is_integral 5 | * @version 0.1 6 | * @date 2022-03-30 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef TYPE_TRAITS 13 | #define TYPE_TRAITS 14 | #define FT_NOEXCEPT throw() 15 | 16 | namespace ft { 17 | 18 | template <typename T, T v> 19 | struct integral_constant { 20 | typedef integral_constant<T, v> type; 21 | typedef T value_type; 22 | static const T value = v; 23 | operator value_type() const FT_NOEXCEPT { return value; } 24 | }; 25 | 26 | typedef integral_constant<bool, true> true_type; 27 | typedef integral_constant<bool, false> false_type; 28 | 29 | template <bool, typename T = void> 30 | struct enable_if {}; 31 | 32 | template <typename T> 33 | struct enable_if<true, T> { 34 | typedef T type; 35 | }; 36 | 37 | template <typename T> 38 | struct _remove_cv { 39 | typedef T type; 40 | }; 41 | 42 | template <typename T> 43 | struct _remove_cv<const T> { 44 | typedef T type; 45 | }; 46 | 47 | template <typename T> 48 | struct _remove_cv<volatile T> { 49 | typedef T type; 50 | }; 51 | 52 | template <typename T> 53 | struct _remove_cv<const volatile T> { 54 | typedef T type; 55 | }; 56 | 57 | template <typename T> 58 | struct remove_cv { 59 | typedef typename _remove_cv<T>::type type; 60 | }; 61 | 62 | template <typename T> 63 | struct _is_integral : public false_type {}; 64 | template <> 65 | struct _is_integral<bool> : public true_type {}; 66 | template <> 67 | struct _is_integral<char> : public true_type {}; 68 | template <> 69 | struct _is_integral<unsigned char> : public true_type {}; 70 | template <> 71 | struct _is_integral<signed char> : public true_type {}; 72 | template <> 73 | struct _is_integral<wchar_t> : public true_type {}; 74 | template <> 75 | struct _is_integral<short> : public true_type {}; 76 | template <> 77 | struct _is_integral<unsigned short> : public true_type {}; 78 | template <> 79 | struct _is_integral<int> : public true_type {}; 80 | template <> 81 | struct _is_integral<unsigned int> : public true_type {}; 82 | template <> 83 | struct _is_integral<long> : public true_type {}; 84 | template <> 85 | struct _is_integral<unsigned long> : public true_type {}; 86 | template <> 87 | struct _is_integral<long long> : public true_type {}; 88 | template <> 89 | struct _is_integral<unsigned long long> : public true_type {}; 90 | 91 | template <typename T> 92 | struct is_integral : public _is_integral<typename remove_cv<T>::type> {}; 93 | 94 | template <typename T, typename U> 95 | struct is_same : public false_type {}; 96 | 97 | template <typename T> 98 | struct is_same<T, T> : public true_type {}; 99 | 100 | template <typename> 101 | struct void_t { 102 | typedef void type; 103 | }; 104 | 105 | } // namespace ft 106 | 107 | #endif // TYPE_TRAITS 108 | -------------------------------------------------------------------------------- /include/utility.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file utility.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief utility (pair, make_pair) 5 | * @version 0.1 6 | * @date 2022-04-10 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #ifndef UTILITY_HPP 13 | #define UTILITY_HPP 14 | #include <functional> 15 | 16 | namespace ft { 17 | 18 | template <typename _T1, typename _T2> 19 | struct pair { 20 | // typedef 21 | typedef _T1 first_type; 22 | typedef _T2 second_type; 23 | 24 | // member variable 25 | _T1 first; 26 | _T2 second; 27 | 28 | // constructor 29 | pair() : first(), second() {} 30 | template <typename _U1, typename _U2> 31 | pair(const pair<_U1, _U2> &other) 32 | : first(other.first), second(other.second) {} 33 | pair(const _T1 &t1, const _T2 &t2) : first(t1), second(t2) {} 34 | 35 | // assign operator 36 | pair &operator=(pair const &other) { 37 | first = other.first; 38 | second = other.second; 39 | return *this; 40 | } 41 | }; 42 | 43 | template <class _T1, class _T2> 44 | bool operator==(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 45 | return lhs.first == rhs.first && lhs.second == rhs.second; 46 | } 47 | 48 | template <class _T1, class _T2> 49 | bool operator!=(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 50 | return !(lhs == rhs); 51 | } 52 | 53 | template <class _T1, class _T2> 54 | bool operator<(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 55 | return lhs.first < rhs.first || 56 | (!(rhs.first < lhs.first) && lhs.second < rhs.second); 57 | } 58 | 59 | template <class _T1, class _T2> 60 | bool operator>(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 61 | return rhs < lhs; 62 | } 63 | 64 | template <class _T1, class _T2> 65 | bool operator>=(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 66 | return !(lhs < rhs); 67 | } 68 | 69 | template <class _T1, class _T2> 70 | bool operator<=(const pair<_T1, _T2> &lhs, const pair<_T1, _T2> &rhs) { 71 | return !(rhs < lhs); 72 | } 73 | 74 | template <typename _T1, typename _T2> 75 | inline pair<_T1, _T2> make_pair(_T1 x, _T2 y) { 76 | return pair<_T1, _T2>(x, y); 77 | } 78 | 79 | template <typename T> 80 | void swap(T &x, T &y) { 81 | T tmp(x); 82 | x = y; 83 | y = tmp; 84 | } 85 | 86 | template <typename pair> 87 | struct select_first { 88 | typename pair::first_type &operator()(pair &__x) const { return __x.first; } 89 | const typename pair::first_type &operator()(const pair &__x) const { 90 | return __x.first; 91 | } 92 | }; 93 | 94 | template <typename T> 95 | struct identity { 96 | T &operator()(T &__x) const { return __x; } 97 | const T &operator()(const T &__x) const { return __x; } 98 | }; 99 | 100 | } // namespace ft 101 | 102 | #endif // UTILITY_HPP -------------------------------------------------------------------------------- /include/vector.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file vector.hpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief vector container 5 | * @version 0.1 6 | * @date 2022-03-27 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include <memory> 13 | 14 | #include "algorithm.hpp" 15 | #include "iterator.hpp" 16 | 17 | #ifndef VECTOR_HPP 18 | #define VECTOR_HPP 19 | 20 | #define FT_NOEXCEPT throw() 21 | 22 | namespace ft { 23 | 24 | /** 25 | * @brief base of Vector to RAII. 26 | * 27 | * @tparam _T: Type of Vector 28 | * @tparam _Allocator: Allocator of Vector 29 | * 30 | * @details 벡터의 데이터가 실제로 저장되는 base. 벡터의 Exception-safety를 31 | * 보장하기 위해 RAII 구조로 작성. 외부에서 객체로 만들 수 없으며 vector 32 | * 클래스에선 이곳에 정의된 메소드들로 데이터에 접근한다. 33 | */ 34 | template <typename _T, typename _Allocator = std::allocator<_T>()> 35 | struct __vector_base { 36 | public: 37 | typedef _Allocator allocator_type; 38 | 39 | protected: 40 | typedef _T value_type; 41 | typedef typename allocator_type::reference reference; 42 | typedef typename allocator_type::const_reference const_reference; 43 | typedef typename allocator_type::size_type size_type; 44 | typedef typename allocator_type::difference_type difference_type; 45 | typedef typename allocator_type::pointer pointer; 46 | typedef typename allocator_type::const_pointer const_pointer; 47 | 48 | pointer __begin_; 49 | pointer __end_; 50 | pointer __end_cap_; 51 | allocator_type __a_; 52 | 53 | __vector_base() FT_NOEXCEPT; 54 | __vector_base(const allocator_type& a) FT_NOEXCEPT; 55 | __vector_base(size_type n); 56 | __vector_base(size_type n, const allocator_type& alloc); 57 | ~__vector_base() FT_NOEXCEPT { 58 | if (__begin_) __a_.deallocate(__begin_, __capacity()); 59 | } 60 | 61 | size_type __capacity() const FT_NOEXCEPT { 62 | return static_cast<size_type>(__end_cap_ - __begin_); 63 | } 64 | 65 | size_type __check_length(size_type __n) { 66 | if (__n > __a_.max_size()) __throw_length_error("vector: size is too big"); 67 | return __n; 68 | } 69 | 70 | void __destruct_storage() FT_NOEXCEPT; 71 | pointer __construct_storage(size_type __n) { 72 | return __n == 0 ? pointer() : __a_.allocate(__n); 73 | }; 74 | 75 | void __copy_data(__vector_base const& _other) FT_NOEXCEPT; 76 | void __copy_data(pointer const& __new_begin_, pointer const& __new_end, 77 | pointer const& __new_end_cap_) FT_NOEXCEPT; 78 | void __swap_data(__vector_base& _other) FT_NOEXCEPT; 79 | 80 | void __throw_length_error(const char* msg) const { 81 | throw std::length_error(msg); 82 | } 83 | void __throw_out_of_range(const char* msg) const { 84 | throw std::out_of_range(msg); 85 | } 86 | 87 | private: 88 | __vector_base(const __vector_base& other) { (void)other; } 89 | __vector_base& operator=(const __vector_base& other) { (void)other; } 90 | }; 91 | 92 | template <typename _T, typename _Allocator> 93 | __vector_base<_T, _Allocator>::__vector_base() FT_NOEXCEPT 94 | : __begin_(NULL), 95 | __end_(NULL), 96 | __end_cap_(NULL), 97 | __a_(std::allocator<_T>()) {} 98 | 99 | template <typename _T, typename _Allocator> 100 | __vector_base<_T, _Allocator>::__vector_base(const allocator_type& a) 101 | FT_NOEXCEPT : __begin_(NULL), 102 | __end_(NULL), 103 | __end_cap_(NULL), 104 | __a_(a) {} 105 | 106 | template <typename _T, typename _Allocator> 107 | __vector_base<_T, _Allocator>::__vector_base(size_type __n) 108 | : __a_(std::allocator<_T>()) { 109 | __begin_ = __construct_storage(__n); 110 | __end_ = __begin_; 111 | __end_cap_ = __begin_ + __n; 112 | } 113 | 114 | template <typename _T, typename _Allocator> 115 | __vector_base<_T, _Allocator>::__vector_base(size_type __n, 116 | const allocator_type& a) 117 | : __a_(a) { 118 | __begin_ = __construct_storage(__n); 119 | __end_ = __begin_; 120 | __end_cap_ = __begin_ + __n; 121 | } 122 | 123 | template <typename _T, typename _Allocator> 124 | void __vector_base<_T, _Allocator>::__copy_data(__vector_base const& _other) 125 | FT_NOEXCEPT { 126 | __begin_ = _other.__begin_; 127 | __end_ = _other.__end_; 128 | __end_cap_ = _other.__end_cap_; 129 | } 130 | 131 | template <typename _T, typename _Allocator> 132 | void __vector_base<_T, _Allocator>::__copy_data( 133 | pointer const& __new_begin_, pointer const& __new_end, 134 | pointer const& __new_end_cap_) FT_NOEXCEPT { 135 | __begin_ = __new_begin_; 136 | __end_ = __new_end; 137 | __end_cap_ = __new_end_cap_; 138 | } 139 | 140 | template <typename _T, typename _Allocator> 141 | void __vector_base<_T, _Allocator>::__swap_data(__vector_base& _other) 142 | FT_NOEXCEPT { 143 | pointer __tmp_begin_(__begin_); 144 | pointer __tmp_end_(__end_); 145 | pointer __tmp_end_cap_(__end_cap_); 146 | allocator_type __tmp_a_(__a_); 147 | this->__copy_data(_other); 148 | this->__a_ = _other.__a_; 149 | _other.__copy_data(__tmp_begin_, __tmp_end_, __tmp_end_cap_); 150 | _other.__a_ = __tmp_a_; 151 | } 152 | 153 | template <typename _T, typename _Allocator> 154 | void __vector_base<_T, _Allocator>::__destruct_storage() FT_NOEXCEPT { 155 | __a_.deallocate(__begin_, __capacity()); 156 | __end_ = __begin_ = __end_cap_ = NULL; 157 | } 158 | 159 | /** 160 | * @brief Iterator for vector. 161 | * 162 | * @tparam _Iter: type of iterator 163 | */ 164 | template <typename _Iter> 165 | class __vector_iterator { 166 | public: 167 | typedef _Iter iterator_type; 168 | typedef typename ft::iterator_traits<iterator_type>::iterator_category 169 | iterator_category; 170 | typedef typename ft::iterator_traits<iterator_type>::value_type value_type; 171 | typedef typename ft::iterator_traits<iterator_type>::difference_type 172 | difference_type; 173 | typedef typename ft::iterator_traits<iterator_type>::pointer pointer; 174 | typedef typename ft::iterator_traits<iterator_type>::reference reference; 175 | 176 | private: 177 | iterator_type __it; 178 | 179 | public: 180 | __vector_iterator() FT_NOEXCEPT {} 181 | template <typename _U> 182 | __vector_iterator( 183 | const __vector_iterator<_U>& __u, 184 | typename enable_if<__is_random_access_iterator<_U>::value>::type* = 185 | 0) // can copy when the category is random_access 186 | FT_NOEXCEPT : __it(__u.base()) {} 187 | 188 | __vector_iterator(iterator_type __x) FT_NOEXCEPT : __it(__x) {} 189 | 190 | const iterator_type& base() const { return __it; } 191 | 192 | // operator 193 | reference operator*() const FT_NOEXCEPT { return *__it; } 194 | pointer operator->() const FT_NOEXCEPT { return __it; } 195 | __vector_iterator& operator++() FT_NOEXCEPT { 196 | ++__it; 197 | return *this; 198 | } 199 | __vector_iterator operator++(int) FT_NOEXCEPT { 200 | __vector_iterator __tmp(*this); 201 | ++(*this); 202 | return __tmp; 203 | } 204 | __vector_iterator& operator--() FT_NOEXCEPT { 205 | --__it; 206 | return *this; 207 | } 208 | __vector_iterator operator--(int) FT_NOEXCEPT { 209 | __vector_iterator __tmp(*this); 210 | --(*this); 211 | return __tmp; 212 | } 213 | __vector_iterator& operator+=(difference_type __n) { 214 | __it += __n; 215 | return *this; 216 | } 217 | __vector_iterator operator+(difference_type __n) const { 218 | __vector_iterator __w(*this); 219 | __w += __n; 220 | return __w; 221 | } 222 | __vector_iterator& operator-=(difference_type __n) { 223 | __it -= __n; 224 | return *this; 225 | } 226 | __vector_iterator operator-(difference_type __n) const { 227 | __vector_iterator __w(*this); 228 | __w -= __n; 229 | return __w; 230 | } 231 | reference operator[](difference_type __n) { return __it[__n]; } 232 | }; 233 | 234 | template <typename _Iter1, typename _Iter2> 235 | bool operator==(const __vector_iterator<_Iter1>& __lhs, 236 | const __vector_iterator<_Iter2>& __rhs) { 237 | return __lhs.base() == __rhs.base(); 238 | } 239 | 240 | template <typename _Iter1, typename _Iter2> 241 | bool operator!=(const __vector_iterator<_Iter1>& __lhs, 242 | const __vector_iterator<_Iter2>& __rhs) { 243 | return __lhs.base() != __rhs.base(); 244 | } 245 | 246 | template <typename _Iter1, typename _Iter2> 247 | bool operator<(const __vector_iterator<_Iter1>& __lhs, 248 | const __vector_iterator<_Iter2>& __rhs) { 249 | return __lhs.base() < __rhs.base(); 250 | } 251 | 252 | template <typename _Iter1, typename _Iter2> 253 | bool operator>(const __vector_iterator<_Iter1>& __lhs, 254 | const __vector_iterator<_Iter2>& __rhs) { 255 | return __lhs.base() > __rhs.base(); 256 | } 257 | 258 | template <typename _Iter1, typename _Iter2> 259 | bool operator>=(const __vector_iterator<_Iter1>& __lhs, 260 | const __vector_iterator<_Iter2>& __rhs) { 261 | return __lhs.base() >= __rhs.base(); 262 | } 263 | 264 | template <typename _Iter1, typename _Iter2> 265 | bool operator<=(const __vector_iterator<_Iter1>& __lhs, 266 | const __vector_iterator<_Iter2>& __rhs) { 267 | return __lhs.base() <= __rhs.base(); 268 | } 269 | 270 | template <typename _Iter1, typename _Iter2> 271 | typename __vector_iterator<_Iter1>::difference_type operator-( 272 | const __vector_iterator<_Iter1>& __lhs, 273 | const __vector_iterator<_Iter2>& __rhs) { 274 | return __lhs.base() - __rhs.base(); 275 | } 276 | 277 | template <typename _Iter> 278 | __vector_iterator<_Iter> operator+( 279 | typename __vector_iterator<_Iter>::difference_type __n, 280 | const __vector_iterator<_Iter>& __it) { 281 | return __vector_iterator<_Iter>(__it.base() + __n); 282 | } 283 | 284 | /** 285 | * @brief vector container class. 286 | * 287 | * @tparam _T: each element type in vector 288 | * @tparam _Allocator: Allocator of vector 289 | */ 290 | template <typename _T, typename _Allocator = std::allocator<_T> > 291 | class vector : private __vector_base<_T, _Allocator> { 292 | private: 293 | typedef __vector_base<_T, _Allocator> __base; 294 | 295 | public: 296 | typedef _T value_type; 297 | typedef _Allocator allocator_type; 298 | typedef typename __base::reference reference; 299 | typedef typename __base::const_reference const_reference; 300 | typedef typename __base::size_type size_type; 301 | typedef typename __base::difference_type difference_type; 302 | typedef typename __base::pointer pointer; 303 | typedef typename __base::const_pointer const_pointer; 304 | 305 | typedef __vector_iterator<pointer> iterator; 306 | typedef __vector_iterator<const_pointer> const_iterator; 307 | typedef ft::reverse_iterator<iterator> reverse_iterator; 308 | typedef ft::reverse_iterator<const_iterator> const_reverse_iterator; 309 | 310 | // constructor 311 | explicit vector(const allocator_type& Alloc = allocator_type()); 312 | 313 | explicit vector(size_type n); 314 | explicit vector(size_type n, const value_type& val); 315 | vector(size_type n, const value_type& val, const allocator_type& Alloc); 316 | 317 | template <typename _InputIterator> 318 | vector(_InputIterator first, 319 | typename enable_if<__is_input_iterator<_InputIterator>::value && 320 | !__is_forward_iterator<_InputIterator>::value, 321 | _InputIterator>::type last, 322 | const allocator_type& Alloc = allocator_type()); 323 | 324 | template <typename _ForwardIterator> 325 | vector(_ForwardIterator first, 326 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 327 | _ForwardIterator>::type last, 328 | const allocator_type& Alloc = allocator_type()); 329 | 330 | vector(const vector<_T, _Allocator>& other); 331 | 332 | // assign operator 333 | vector& operator=(const vector& rhs); 334 | 335 | // iterators 336 | iterator begin() FT_NOEXCEPT { return this->__begin_; } 337 | const_iterator begin() const { return this->__begin_; } 338 | iterator end() { return this->__end_; } 339 | const_iterator end() const { return this->__end_; } 340 | reverse_iterator rbegin() { return reverse_iterator(end()); } 341 | const_reverse_iterator rbegin() const { 342 | return const_reverse_iterator(end()); 343 | } 344 | reverse_iterator rend() { return reverse_iterator(begin()); } 345 | const_reverse_iterator rend() const { 346 | return const_reverse_iterator(begin()); 347 | } 348 | 349 | // capacity 350 | size_type size() const { return ft::distance(this->__begin_, this->__end_); } 351 | size_type max_size() const { 352 | return std::min( 353 | static_cast<size_type>(std::numeric_limits<difference_type>::max()), 354 | this->__a_.max_size()); 355 | } 356 | void resize(size_type n, value_type val = value_type()); 357 | size_type capacity() const { return this->__capacity(); } 358 | bool empty() const { return this->__begin_ == this->__end_; } 359 | void reserve(size_type n); 360 | 361 | // element access 362 | reference operator[](size_type n) { return reference(*(this->__begin_ + n)); } 363 | const_reference operator[](size_type n) const { 364 | return const_reference(*(this->__begin_ + n)); 365 | } 366 | reference at(size_type n) { 367 | if (n > this->size()) this->__throw_out_of_range("vector: out of range"); 368 | return *(this->__begin_ + n); 369 | } 370 | const_reference at(size_type n) const { 371 | if (n > this->size()) this->__throw_out_of_range("vector: out of range"); 372 | return *(this->__begin_ + n); 373 | } 374 | reference front() { return *this->__begin_; } 375 | const_reference front() const { return *this->__begin_; } 376 | reference back() { return *(this->__end_ - 1); } 377 | const_reference back() const { return *(this->__end_ - 1); } 378 | 379 | // modifiers 380 | template <typename _InputIterator> 381 | void assign( 382 | _InputIterator first, 383 | typename enable_if<__is_input_iterator<_InputIterator>::value && 384 | !__is_forward_iterator<_InputIterator>::value, 385 | _InputIterator>::type last); 386 | template <typename _ForwardIterator> 387 | void assign(_ForwardIterator first, 388 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 389 | _ForwardIterator>::type last); 390 | void assign(size_type n, const value_type& val); 391 | void push_back(const value_type& val); 392 | void pop_back() FT_NOEXCEPT; 393 | iterator insert(iterator position, const value_type& val); 394 | void insert(iterator position, size_type n, const value_type& val); 395 | template <typename _InputIterator> 396 | void insert( 397 | iterator position, _InputIterator first, 398 | typename enable_if<__is_input_iterator<_InputIterator>::value && 399 | !__is_forward_iterator<_InputIterator>::value, 400 | _InputIterator>::type last); 401 | template <typename _ForwardIterator> 402 | void insert(iterator position, _ForwardIterator first, 403 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 404 | _ForwardIterator>::type last); 405 | iterator erase(iterator position); 406 | iterator erase(iterator first, iterator last); 407 | void swap(vector& x) { this->__swap_data(x); } 408 | void clear() FT_NOEXCEPT { 409 | if (this->__begin_) __destroy_from_end(this->__begin_); 410 | } 411 | 412 | // Allocator 413 | allocator_type get_allocator() const FT_NOEXCEPT { return this->__a_; } 414 | 415 | ~vector() FT_NOEXCEPT { 416 | if (this->__begin_) { 417 | clear(); 418 | this->__destruct_storage(); 419 | } 420 | } 421 | 422 | private: 423 | void __reconstruct_push_back(const value_type& val); 424 | void __reallocate(size_type __n); 425 | void __destroy_from_end(pointer __new_end); 426 | }; 427 | 428 | // constructor 429 | 430 | template <typename _T, typename _Allocator> 431 | vector<_T, _Allocator>::vector(const allocator_type& Alloc) 432 | : __vector_base<_T, _Allocator>(size_type(), Alloc) {} 433 | 434 | template <typename _T, typename _Allocator> 435 | vector<_T, _Allocator>::vector(size_type n) 436 | : __vector_base<_T, _Allocator>(n, allocator_type()) { 437 | std::uninitialized_fill(this->__begin_, this->__begin_ + n, value_type()); 438 | this->__end_ += n; 439 | } 440 | 441 | template <typename _T, typename _Allocator> 442 | vector<_T, _Allocator>::vector(size_type n, const value_type& val) 443 | : __vector_base<_T, _Allocator>(n, allocator_type()) { 444 | std::uninitialized_fill(this->__begin_, this->__begin_ + n, val); 445 | this->__end_ += n; 446 | } 447 | 448 | template <typename _T, typename _Allocator> 449 | vector<_T, _Allocator>::vector(size_type n, const value_type& val, 450 | const allocator_type& Alloc) 451 | : __vector_base<_T, _Allocator>(n, Alloc) { 452 | std::uninitialized_fill(this->__begin_, this->__begin_ + n, val); 453 | this->__end_ += n; 454 | } 455 | 456 | template <typename _T, typename _Allocator> 457 | template <typename _InputIterator> 458 | vector<_T, _Allocator>::vector( 459 | _InputIterator first, 460 | typename enable_if<__is_input_iterator<_InputIterator>::value && 461 | !__is_forward_iterator<_InputIterator>::value, 462 | _InputIterator>::type last, 463 | const allocator_type& Alloc) 464 | : __vector_base<_T, _Allocator>(size_type(), Alloc) { 465 | for (; first != last; ++first) push_back(*first); 466 | } 467 | 468 | template <typename _T, typename _Allocator> 469 | template <typename _ForwardIterator> 470 | vector<_T, _Allocator>::vector( 471 | _ForwardIterator first, 472 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 473 | _ForwardIterator>::type last, 474 | const allocator_type& Alloc) 475 | : __vector_base<_T, _Allocator>( 476 | static_cast<size_type>(ft::distance(first, last)), Alloc) { 477 | this->__end_ = std::uninitialized_copy(first, last, this->__begin_); 478 | } 479 | 480 | template <typename _T, typename _Allocator> 481 | vector<_T, _Allocator>::vector(const vector<_T, _Allocator>& other) 482 | : __vector_base<_T, _Allocator>(other.capacity()) { 483 | clear(); 484 | this->__end_ = 485 | std::uninitialized_copy(other.__begin_, other.__end_, this->__begin_); 486 | } 487 | 488 | template <typename _T, typename _Allocator> 489 | vector<_T, _Allocator>& vector<_T, _Allocator>::operator=( 490 | const vector<_T, _Allocator>& other) { 491 | if (this != &other) { 492 | if (this->__a_ != other.__a_) { 493 | clear(); 494 | this->__a_.deallocate(this->__begin_, capacity()); 495 | this->__begin_ = this->__end_ = this->__end_cap_ = NULL; 496 | this->__a_ = other.__a_; 497 | } 498 | assign(other.__begin_, other.__end_); 499 | } 500 | return *this; 501 | } 502 | 503 | // private member function 504 | 505 | template <typename _T, typename _Allocator> 506 | void vector<_T, _Allocator>::__reconstruct_push_back(const value_type& val) { 507 | size_type __cap = this->__capacity(); 508 | size_type __max_size = max_size(); 509 | size_type __new_size = __cap > (__max_size >> 1) ? __max_size : __cap << 1; 510 | if (__new_size == 0) __new_size = 1; 511 | reserve(__new_size); 512 | this->__a_.construct(this->__end_, val); 513 | ++this->__end_; 514 | } 515 | 516 | template <typename _T, typename _Allocator> 517 | void vector<_T, _Allocator>::__reallocate(size_type __n) { 518 | vector<_T, _Allocator> tmp(__n); 519 | std::uninitialized_copy(this->__begin_, this->__end_, tmp.__begin_); 520 | tmp.__end_ = tmp.__begin_ + size(); 521 | this->__swap_data(tmp); 522 | } 523 | 524 | template <typename _T, typename _Allocator> 525 | void vector<_T, _Allocator>::__destroy_from_end(pointer __new_end) { 526 | pointer __be_end = this->__end_; 527 | while (__new_end != __be_end) { 528 | --__be_end; 529 | this->__a_.destroy(__be_end); 530 | } 531 | this->__end_ = __new_end; 532 | } 533 | 534 | // public member function 535 | 536 | // capacity 537 | 538 | template <typename _T, typename _Allocator> 539 | void vector<_T, _Allocator>::reserve(size_type n) { 540 | size_type __new_size = this->__check_length(n); 541 | if (__new_size > capacity()) { 542 | __reallocate(__new_size); 543 | } 544 | } 545 | 546 | template <typename _T, typename _Allocator> 547 | void vector<_T, _Allocator>::resize(size_type n, value_type val) { 548 | size_type __prev_size = size(); 549 | if (n < __prev_size) { 550 | __destroy_from_end(this->__begin_ + n); 551 | return; 552 | } else if (n > capacity()) { 553 | __reallocate(n); 554 | } 555 | insert(end(), n - __prev_size, val); 556 | } 557 | 558 | // modifiers 559 | 560 | template <typename _T, typename _Allocator> 561 | void vector<_T, _Allocator>::assign(size_type n, const value_type& val) { 562 | if (n < capacity()) { 563 | clear(); 564 | std::uninitialized_fill(this->__begin_, this->__begin_ + n, val); 565 | this->__end_ += n; 566 | } else { 567 | vector<_T, _Allocator> tmp(n, val); 568 | this->__swap_data(tmp); 569 | } 570 | } 571 | 572 | template <typename _T, typename _Allocator> 573 | template <typename _InputIterator> 574 | void vector<_T, _Allocator>::assign( 575 | _InputIterator first, 576 | typename enable_if<__is_input_iterator<_InputIterator>::value && 577 | !__is_forward_iterator<_InputIterator>::value, 578 | _InputIterator>::type last) { 579 | clear(); 580 | for (; first != last; ++first) { 581 | push_back(*first); 582 | } 583 | } 584 | 585 | template <typename _T, typename _Allocator> 586 | template <typename _ForwardIterator> 587 | void vector<_T, _Allocator>::assign( 588 | _ForwardIterator first, 589 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 590 | _ForwardIterator>::type last) { 591 | size_type __new_n = ft::distance(first, last); 592 | if (__new_n < capacity()) { 593 | clear(); 594 | this->__end_ = std::uninitialized_copy(first, last, this->__begin_); 595 | } else { 596 | vector<_T, _Allocator> tmp(first, last); 597 | this->__swap_data(tmp); 598 | } 599 | } 600 | 601 | template <typename _T, typename _Allocator> 602 | void vector<_T, _Allocator>::push_back(const value_type& val) { 603 | if (this->__end_ != this->__end_cap_) 604 | this->__a_.construct(this->__end_++, val); 605 | else 606 | __reconstruct_push_back(val); 607 | } 608 | 609 | template <typename _T, typename _Allocator> 610 | void vector<_T, _Allocator>::pop_back() FT_NOEXCEPT { 611 | if (!empty()) __destroy_from_end(this->__end_ - 1); 612 | } 613 | 614 | template <typename _T, typename _Allocator> 615 | typename vector<_T, _Allocator>::iterator vector<_T, _Allocator>::insert( 616 | iterator position, const value_type& val) { 617 | difference_type __diff = position - begin(); 618 | if (this->__end_ == this->__end_cap_) reserve(size_type(capacity() + 1)); 619 | pointer __p = this->__begin_ + __diff; 620 | pointer __old_end = this->__end_; 621 | while (__old_end != __p) { 622 | --__old_end; 623 | this->__a_.construct(__old_end + 1, *(__old_end)); 624 | this->__a_.destroy(__old_end); 625 | } 626 | this->__a_.construct(__p, val); 627 | ++this->__end_; 628 | return iterator(this->__begin_ + __diff); 629 | } 630 | 631 | template <typename _T, typename _Allocator> 632 | void vector<_T, _Allocator>::insert(iterator position, size_type n, 633 | const value_type& val) { 634 | difference_type __diff = position - begin(); 635 | if (size() + n > capacity()) reserve(size() + n); 636 | pointer __p = this->__begin_ + __diff; 637 | pointer __old_end = this->__end_; 638 | while (__old_end != __p) { 639 | --__old_end; 640 | this->__a_.construct(__old_end + n, *(__old_end)); 641 | this->__a_.destroy(__old_end); 642 | } 643 | std::uninitialized_fill(__p, __p + n, val); 644 | this->__end_ += n; 645 | } 646 | 647 | template <typename _T, typename _Allocator> 648 | template <typename _InputIterator> 649 | void vector<_T, _Allocator>::insert( 650 | iterator position, _InputIterator first, 651 | typename enable_if<__is_input_iterator<_InputIterator>::value && 652 | !__is_forward_iterator<_InputIterator>::value, 653 | _InputIterator>::type last) { 654 | difference_type __diff = position - begin(); 655 | pointer __p = this->__begin_ + __diff; 656 | pointer __prev_end_ = this->__end_; 657 | for (int i = 0; first != last; ++first, ++i) { 658 | insert(position + i, *first); 659 | } 660 | } 661 | 662 | template <typename _T, typename _Allocator> 663 | template <typename _ForwardIterator> 664 | void vector<_T, _Allocator>::insert( 665 | iterator position, _ForwardIterator first, 666 | typename enable_if<__is_forward_iterator<_ForwardIterator>::value, 667 | _ForwardIterator>::type last) { 668 | difference_type __in_size = ft::distance(first, last); 669 | difference_type __diff = position - begin(); 670 | if (__in_size <= 0) return; 671 | if (__in_size + size() > capacity()) reserve(__in_size + size()); 672 | pointer __p = this->__begin_ + __diff; 673 | pointer __old_end = this->__end_; 674 | while (__old_end != __p) { 675 | --__old_end; 676 | this->__a_.construct(__old_end + __in_size, *(__old_end)); 677 | this->__a_.destroy(__old_end); 678 | } 679 | std::uninitialized_copy(first, last, __p); 680 | this->__end_ += __in_size; 681 | } 682 | 683 | template <typename _T, typename _Allocator> 684 | typename vector<_T, _Allocator>::iterator vector<_T, _Allocator>::erase( 685 | iterator position) { 686 | difference_type __diff = position - begin(); 687 | pointer __p = this->__begin_ + __diff; 688 | 689 | this->__a_.destroy(__p); 690 | this->__a_.destroy(std::uninitialized_copy(__p + 1, this->__end_--, __p)); 691 | return (iterator(this->__begin_ + __diff)); 692 | } 693 | 694 | template <typename _T, typename _Allocator> 695 | typename vector<_T, _Allocator>::iterator vector<_T, _Allocator>::erase( 696 | iterator first, iterator last) { 697 | difference_type __diff = first - begin(); 698 | pointer __p = this->__begin_ + __diff; 699 | 700 | if (last == end()) { 701 | __destroy_from_end(__p); 702 | return iterator(this->__begin_ + __diff); 703 | } 704 | 705 | difference_type __range = last - first; 706 | pointer __p_last = __p + __range; 707 | pointer __new_end = this->__end_ - __range; 708 | 709 | for (difference_type i = 0; i <= __range; ++i) { 710 | this->__a_.destroy(__p + i); 711 | if (i <= this->__end_ - __p_last) 712 | this->__a_.construct(__p + i, *(__p_last + i)); 713 | } 714 | __destroy_from_end(__new_end); 715 | return (iterator(this->__begin_ + __diff)); 716 | } 717 | 718 | // non-member function overloads 719 | 720 | // comparision operators 721 | 722 | template <typename _T, typename _Allocator> 723 | inline bool operator==(const vector<_T, _Allocator>& lhs, 724 | const vector<_T, _Allocator>& rhs) { 725 | return lhs.size() == rhs.size() && 726 | ft::equal(lhs.begin(), lhs.end(), rhs.begin()); 727 | } 728 | 729 | template <typename _T, typename _Allocator> 730 | inline bool operator!=(const vector<_T, _Allocator>& lhs, 731 | const vector<_T, _Allocator>& rhs) { 732 | return !(lhs == rhs); 733 | } 734 | 735 | template <typename _T, typename _Allocator> 736 | inline bool operator<(const vector<_T, _Allocator>& lhs, 737 | const vector<_T, _Allocator>& rhs) { 738 | return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), 739 | rhs.end()); 740 | } 741 | 742 | template <typename _T, typename _Allocator> 743 | inline bool operator<=(const vector<_T, _Allocator>& lhs, 744 | const vector<_T, _Allocator>& rhs) { 745 | return !(lhs > rhs); 746 | } 747 | 748 | template <typename _T, typename _Allocator> 749 | inline bool operator>(const vector<_T, _Allocator>& lhs, 750 | const vector<_T, _Allocator>& rhs) { 751 | return rhs < lhs; 752 | } 753 | 754 | template <typename _T, typename _Allocator> 755 | inline bool operator>=(const vector<_T, _Allocator>& lhs, 756 | const vector<_T, _Allocator>& rhs) { 757 | return !(rhs > lhs); 758 | } 759 | 760 | // swap 761 | template <typename _T, typename _Allocator> 762 | inline void swap(ft::vector<_T, _Allocator>& x, ft::vector<_T, _Allocator>& y) { 763 | x.swap(y); 764 | } 765 | 766 | } // namespace ft 767 | 768 | #endif // VECTOR_HPP 769 | -------------------------------------------------------------------------------- /src/__tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file __tree.cpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief RB-tree algorithms implementation 5 | * @version 0.1 6 | * @date 2022-04-11 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include "__tree.hpp" 13 | 14 | #include "utility.hpp" 15 | 16 | namespace ft { 17 | 18 | __tree_node_base *__minimum(__tree_node_base *__x) FT_NOEXCEPT { 19 | while (__x->__left_ != NULL) __x = __x->__left_; 20 | return __x; 21 | } 22 | 23 | const __tree_node_base *__minimum(const __tree_node_base *__x) FT_NOEXCEPT { 24 | while (__x->__left_ != NULL) __x = __x->__left_; 25 | return __x; 26 | } 27 | 28 | __tree_node_base *__maximum(__tree_node_base *__x) FT_NOEXCEPT { 29 | while (__x->__right_ != NULL) __x = __x->__right_; 30 | return __x; 31 | } 32 | 33 | const __tree_node_base *__maximum(const __tree_node_base *__x) FT_NOEXCEPT { 34 | while (__x->__right_ != NULL) __x = __x->__right_; 35 | return __x; 36 | } 37 | 38 | // Return: next node by in-order traverse 39 | static __tree_node_base *local_tree_increment(__tree_node_base *__x) 40 | FT_NOEXCEPT { 41 | if (__x->__right_ != NULL) { 42 | return __minimum(__x->__right_); 43 | } 44 | __tree_node_base *__y = __x->__parent_; 45 | while (__x == __y->__right_) { 46 | __x = __y; 47 | __y = __y->__parent_; 48 | } 49 | if (__x->__right_ != __y) { 50 | __x = __y; 51 | } 52 | return __x; 53 | } 54 | 55 | __tree_node_base *__tree_increment(__tree_node_base *__x) FT_NOEXCEPT { 56 | return local_tree_increment(__x); 57 | } 58 | 59 | const __tree_node_base *__tree_increment(const __tree_node_base *__x) 60 | FT_NOEXCEPT { 61 | return local_tree_increment(const_cast<__tree_node_base *>(__x)); 62 | } 63 | 64 | // Return: prev node by in-order traverse 65 | static __tree_node_base *local_tree_decrement(__tree_node_base *__x) { 66 | if (__x->__color_ == RED && __x->__parent_->__parent_ == __x) { 67 | return __x->__right_; 68 | } 69 | if (__x->__left_ != NULL) { 70 | return __maximum(__x->__left_); 71 | } 72 | __tree_node_base *__y = __x->__parent_; 73 | while (__x == __y->__left_) { 74 | __x = __y; 75 | __y = __y->__parent_; 76 | } 77 | return __y; 78 | } 79 | 80 | __tree_node_base *__tree_decrement(__tree_node_base *__x) FT_NOEXCEPT { 81 | return local_tree_decrement(__x); 82 | } 83 | const __tree_node_base *__tree_decrement(const __tree_node_base *__x) 84 | FT_NOEXCEPT { 85 | return local_tree_decrement(const_cast<__tree_node_base *>(__x)); 86 | } 87 | 88 | /** 89 | * @brief Tree rotate left 90 | * 91 | * @param __x: node to rotate 92 | * @param __root: root of tree 93 | */ 94 | void __tree_rotate_left(__tree_node_base *const __x, 95 | __tree_node_base *&__root) { 96 | __tree_node_base *const __y = __x->__right_; 97 | 98 | __x->__right_ = __y->__left_; 99 | if (__y->__left_ != NULL) __y->__left_->__parent_ = __x; 100 | __y->__parent_ = __x->__parent_; 101 | 102 | if (__x == __root) { 103 | __root = __y; 104 | } else if (__x == __x->__parent_->__left_) { 105 | __x->__parent_->__left_ = __y; 106 | } else { 107 | __x->__parent_->__right_ = __y; 108 | } 109 | __y->__left_ = __x; 110 | __x->__parent_ = __y; 111 | } 112 | 113 | /** 114 | * @brief Tree rotate right 115 | * 116 | * @param __x: node to rotate 117 | * @param __root: root of tree 118 | */ 119 | void __tree_rotate_right(__tree_node_base *const __x, 120 | __tree_node_base *&__root) { 121 | __tree_node_base *const __y = __x->__left_; 122 | 123 | __x->__left_ = __y->__right_; 124 | if (__y->__right_ != NULL) __y->__right_->__parent_ = __x; 125 | __y->__parent_ = __x->__parent_; 126 | 127 | if (__x == __root) { 128 | __root = __y; 129 | } else if (__x == __x->__parent_->__right_) { 130 | __x->__parent_->__right_ = __y; 131 | } else { 132 | __x->__parent_->__left_ = __y; 133 | } 134 | __y->__right_ = __x; 135 | __x->__parent_ = __y; 136 | } 137 | 138 | static void local_insert_new_node(const bool __insert_left, 139 | __tree_node_base *&__x, 140 | __tree_node_base *&__p, 141 | __tree_node_base &__header) FT_NOEXCEPT { 142 | // initiate new node 143 | __x->__parent_ = __p; 144 | __x->__right_ = NULL; 145 | __x->__left_ = NULL; 146 | __x->__color_ = RED; 147 | 148 | // __p의 left에 __x를 삽입 149 | if (__insert_left) { 150 | __p->__left_ = __x; // __p가 __header여도 leftmost = __x 유지 151 | 152 | // 트리에 노드가 하나도 없는 경우 153 | if (__p == &__header) { 154 | __header.__parent_ = __x; 155 | __header.__right_ = __x; 156 | } else if (__p == __header.__left_) { 157 | __header.__left_ = __x; // __p가 leftmost인 경우 __x가 leftmost 158 | } 159 | } else { // __p의 right에 __x 삽입 160 | __p->__right_ = __x; 161 | if (__p == __header.__right_) 162 | __header.__right_ = __x; // __p가 rightmost인 경우 __x가 rightmost 163 | } 164 | } 165 | 166 | static void local_insert_fixup(__tree_node_base *&__x, 167 | __tree_node_base *&__root) { 168 | while (__x != __root && __x->__parent_->__color_ == RED) { 169 | __tree_node_base *const __xpp = __x->__parent_->__parent_; 170 | 171 | if (__x->__parent_ == __xpp->__left_) { 172 | __tree_node_base *const __y = __xpp->__right_; 173 | 174 | if (__y && __y->__color_ == RED) { // __x의 uncle 노드가 RED(case 1) 175 | __x->__parent_->__color_ = BLACK; 176 | __y->__color_ = BLACK; 177 | __xpp->__color_ = RED; 178 | __x = __xpp; 179 | } else { // __x의 uncle 노드가 black (case 2) 180 | if (__x == __x->__parent_->__right_) { 181 | __x = __x->__parent_; 182 | __tree_rotate_left(__x, __root); 183 | } 184 | __x->__parent_->__color_ = BLACK; // case 3 185 | __xpp->__color_ = RED; 186 | __tree_rotate_right(__xpp, __root); 187 | } 188 | } else { 189 | __tree_node_base *const __y = __xpp->__left_; 190 | 191 | if (__y && __y->__color_ == RED) { // sym case 1 192 | __x->__parent_->__color_ = BLACK; 193 | __y->__color_ = BLACK; 194 | __xpp->__color_ = RED; 195 | __x = __xpp; 196 | } else { 197 | if (__x == __x->__parent_->__left_) { // sym case 2 198 | __x = __x->__parent_; 199 | __tree_rotate_right(__x, __root); 200 | } 201 | __x->__parent_->__color_ = BLACK; // sym case 3 202 | __xpp->__color_ = RED; 203 | __tree_rotate_left(__xpp, __root); 204 | } 205 | } 206 | } 207 | __root->__color_ = BLACK; 208 | } 209 | 210 | /** 211 | * @brief Insert new node in tree and rebalance. 212 | * __x와 __p가 들어갈 위치는 찾아서 들어온다고 가정. 213 | * __x가 처음 insert 된다면, left에 insert (__p가 header이므로) 214 | * header의 root, leftmost, rightmost를 잘 저장 215 | * 216 | * @param __insert_left : insert left or not 217 | * @param __x : Node to insert 218 | * @param __p : Parent Node 219 | * @param __header : head of rb-tree 220 | */ 221 | void __tree_insert_and_fixup(const bool __insert_left, __tree_node_base *__x, 222 | __tree_node_base *__p, 223 | __tree_node_base &__header) FT_NOEXCEPT { 224 | __tree_node_base *&__root = __header.__parent_; 225 | local_insert_new_node(__insert_left, __x, __p, __header); 226 | local_insert_fixup(__x, __root); 227 | } 228 | 229 | static void local_erase_node(__tree_node_base *const &__z, 230 | __tree_node_base *&__y, __tree_node_base *&__x, 231 | __tree_node_base *&__x_p, 232 | __tree_node_base &__header) { 233 | __tree_node_base *&__root = __header.__parent_; 234 | __tree_node_base *&__leftmost = __header.__left_; 235 | __tree_node_base *&__rightmost = __header.__right_; 236 | 237 | if (__y->__left_ != NULL && __y->__right_ != NULL) { 238 | __y = __minimum(__y->__right_); // __y: successor of __Z 239 | __x = __y->__right_; 240 | 241 | __z->__left_->__parent_ = __y; 242 | __y->__left_ = __z->__left_; 243 | if (__y != __z->__right_) { 244 | __x_p = __y->__parent_; 245 | if (__x) __x->__parent_ = __y->__parent_; 246 | __y->__parent_->__left_ = __x; 247 | __y->__right_ = __z->__right_; 248 | __z->__right_->__parent_ = __y; 249 | } else 250 | __x_p = __y; 251 | if (__root == __z) 252 | __root = __y; 253 | else if (__z->__parent_->__left_ == __z) 254 | __z->__parent_->__left_ = __y; 255 | else 256 | __z->__parent_->__right_ = __y; 257 | __y->__parent_ = __z->__parent_; 258 | ft::swap(__y->__color_, __z->__color_); 259 | __y = __z; // __y points to node actually deleted 260 | return; 261 | } 262 | 263 | __x = (__z->__left_ == NULL) ? __z->__right_ : __z->__left_; 264 | __x_p = __z->__parent_; 265 | if (__x) __x->__parent_ = __z->__parent_; 266 | if (__root == __z) 267 | __root = __x; 268 | else if (__z->__parent_->__left_ == __z) 269 | __z->__parent_->__left_ = __x; 270 | else 271 | __z->__parent_->__right_ = __x; 272 | if (__leftmost == __z) { 273 | if (__z->__right_ == NULL) 274 | __leftmost = __z->__parent_; 275 | else 276 | __leftmost = __minimum(__x); 277 | } 278 | if (__rightmost == __z) { 279 | if (__z->__left_ == NULL) 280 | __rightmost = __z->__parent_; 281 | else 282 | __rightmost = __maximum(__x); 283 | } 284 | } 285 | 286 | inline static bool local_erase_fixup_left(__tree_node_base *&__x, 287 | __tree_node_base *&__x_p, 288 | __tree_node_base *&__root) { 289 | __tree_node_base *__w = __x_p->__right_; 290 | if (__w->__color_ == RED) { 291 | __w->__color_ = BLACK; 292 | __x_p->__color_ = RED; 293 | __tree_rotate_left(__x_p, __root); 294 | __w = __x_p->__right_; 295 | } 296 | if ((__w->__left_ == NULL || __w->__left_->__color_ == BLACK) && 297 | (__w->__right_ == NULL || __w->__right_->__color_ == BLACK)) { 298 | __w->__color_ = RED; 299 | __x = __x_p; 300 | __x_p = __x_p->__parent_; 301 | } else { 302 | if (__w->__right_ == NULL || __w->__right_->__color_ == BLACK) { 303 | __w->__left_->__color_ = BLACK; 304 | __w->__color_ = RED; 305 | __tree_rotate_right(__w, __root); 306 | __w = __x_p->__right_; 307 | } 308 | __w->__color_ = __x_p->__color_; 309 | __x_p->__color_ = BLACK; 310 | if (__w->__right_) __w->__right_->__color_ = BLACK; 311 | __tree_rotate_left(__x_p, __root); 312 | return true; 313 | } 314 | return false; 315 | } 316 | 317 | inline static bool local_erase_fixup_right(__tree_node_base *&__x, 318 | __tree_node_base *&__x_p, 319 | __tree_node_base *&__root) { 320 | __tree_node_base *__w = __x_p->__left_; 321 | if (__w->__color_ == RED) { 322 | __w->__color_ = BLACK; 323 | __x_p->__color_ = RED; 324 | __tree_rotate_right(__x_p, __root); 325 | __w = __x_p->__left_; 326 | } 327 | if ((__w->__right_ == NULL || __w->__right_->__color_ == BLACK) && 328 | (__w->__left_ == NULL || __w->__left_->__color_ == BLACK)) { 329 | __w->__color_ = RED; 330 | __x = __x_p; 331 | __x_p = __x_p->__parent_; 332 | } else { 333 | if (__w->__left_ == NULL || __w->__left_->__color_ == BLACK) { 334 | __w->__right_->__color_ = BLACK; 335 | __w->__color_ = RED; 336 | __tree_rotate_left(__w, __root); 337 | __w = __x_p->__left_; 338 | } 339 | __w->__color_ = __x_p->__color_; 340 | __x_p->__color_ = BLACK; 341 | if (__w->__left_) __w->__left_->__color_ = BLACK; 342 | __tree_rotate_right(__x_p, __root); 343 | return true; 344 | } 345 | return false; 346 | } 347 | 348 | static void local_erase_fixup(__tree_node_base *&__x, __tree_node_base *&__x_p, 349 | __tree_node_base *&__root) { 350 | bool __is_end = false; 351 | while (__x != __root && (__x == NULL || __x->__color_ == BLACK) && 352 | !__is_end) { 353 | if (__x == __x_p->__left_) { 354 | __is_end = local_erase_fixup_left(__x, __x_p, __root); 355 | } else { 356 | __is_end = local_erase_fixup_right(__x, __x_p, __root); 357 | } 358 | } 359 | if (__x) __x->__color_ = BLACK; 360 | } 361 | 362 | /** 363 | * @brief Delete Node in tree and rebalance and return deleted node 364 | * __y : Node to replace __z 365 | * __x : child node of __y 366 | * __x_p : parent of __x 367 | * 368 | * @param __z : node to delete 369 | * @param __header : head of rb-tree 370 | * @return __tree_node_base* 371 | */ 372 | __tree_node_base *__tree_erase_and_fixup( 373 | __tree_node_base *const __z, __tree_node_base &__header) FT_NOEXCEPT { 374 | __tree_node_base *&__root = __header.__parent_; 375 | __tree_node_base *__y = __z; 376 | __tree_node_base *__x = NULL; 377 | __tree_node_base *__x_p = NULL; 378 | 379 | local_erase_node(__z, __y, __x, __x_p, __header); 380 | if (__y->__color_ != RED) local_erase_fixup(__x, __x_p, __root); 381 | return __y; 382 | } 383 | 384 | void __tree_header::__tree_reset() { 385 | __header_.__parent_ = NULL; 386 | __header_.__left_ = &__header_; 387 | __header_.__right_ = &__header_; 388 | __node_count_ = 0; 389 | } 390 | 391 | void __tree_header::__tree_move_data(__tree_header &other) { 392 | __header_.__color_ = other.__header_.__color_; 393 | __header_.__parent_ = other.__header_.__parent_; 394 | __header_.__left_ = other.__header_.__left_; 395 | __header_.__right_ = other.__header_.__right_; 396 | __header_.__parent_->__parent_ = &__header_; 397 | __node_count_ = other.__node_count_; 398 | 399 | other.__tree_reset(); 400 | } 401 | 402 | } // namespace ft -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include <deque> 2 | #include <iostream> 3 | #include <string> 4 | #if 0 // CREATE A REAL STL EXAMPLE 5 | #include <map> 6 | #include <set> 7 | #include <stack> 8 | #include <vector> 9 | namespace ft = std; 10 | #else 11 | #include <map.hpp> 12 | #include <set.hpp> 13 | #include <stack.hpp> 14 | #include <vector.hpp> 15 | #endif 16 | 17 | #include <stdlib.h> 18 | 19 | #define MAX_RAM 4294967296 20 | #define BUFFER_SIZE 4096 21 | struct Buffer { 22 | int idx; 23 | char buff[BUFFER_SIZE]; 24 | }; 25 | 26 | #define COUNT (MAX_RAM / (int)sizeof(Buffer)) 27 | 28 | template <typename T> 29 | class MutantStack : public ft::stack<T> { 30 | public: 31 | MutantStack() {} 32 | MutantStack(const MutantStack<T>& src) { *this = src; } 33 | MutantStack<T>& operator=(const MutantStack<T>& rhs) { 34 | this->c = rhs.c; 35 | return *this; 36 | } 37 | ~MutantStack() {} 38 | 39 | typedef typename ft::stack<T>::container_type::iterator iterator; 40 | 41 | iterator begin() { return this->c.begin(); } 42 | iterator end() { return this->c.end(); } 43 | }; 44 | 45 | int main(int argc, char** argv) { 46 | if (argc != 2) { 47 | std::cerr << "Usage: ./test seed" << std::endl; 48 | std::cerr << "Provide a seed please" << std::endl; 49 | std::cerr << "Count value:" << COUNT << std::endl; 50 | return 1; 51 | } 52 | const int seed = atoi(argv[1]); 53 | srand(seed); 54 | 55 | ft::vector<std::string> vector_str; 56 | ft::vector<int> vector_int; 57 | ft::stack<int> stack_int; 58 | ft::vector<Buffer> vector_buffer; 59 | ft::stack<Buffer, std::deque<Buffer> > stack_deq_buffer; 60 | ft::map<int, int> map_int; 61 | ft::set<int> set_int; 62 | 63 | for (int i = 0; i < COUNT; i++) { 64 | vector_buffer.push_back(Buffer()); 65 | } 66 | 67 | for (int i = 0; i < COUNT; i++) { 68 | const int idx = rand() % COUNT; 69 | vector_buffer[idx].idx = 5; 70 | } 71 | ft::vector<Buffer>().swap(vector_buffer); 72 | 73 | try { 74 | for (int i = 0; i < COUNT; i++) { 75 | const int idx = rand() % COUNT; 76 | vector_buffer.at(idx); 77 | std::cerr << "Error: THIS VECTOR SHOULD BE EMPTY!!" << std::endl; 78 | } 79 | } catch (const std::exception& e) { 80 | // NORMAL ! :P 81 | } 82 | 83 | for (int i = 0; i < COUNT; ++i) { 84 | map_int.insert(ft::make_pair(rand(), rand())); 85 | } 86 | 87 | int sum = 0; 88 | for (int i = 0; i < 10000; i++) { 89 | int access = rand(); 90 | sum += map_int[access]; 91 | } 92 | std::cout << "should be constant with the same seed: " << sum << std::endl; 93 | 94 | { ft::map<int, int> copy = map_int; } 95 | 96 | for (int i = 0; i < COUNT; ++i) { 97 | set_int.insert(rand()); 98 | } 99 | 100 | { ft::set<int> copy = set_int; } 101 | 102 | MutantStack<char> iterable_stack; 103 | for (char letter = 'a'; letter <= 'z'; letter++) iterable_stack.push(letter); 104 | for (MutantStack<char>::iterator it = iterable_stack.begin(); 105 | it != iterable_stack.end(); it++) { 106 | std::cout << *it; 107 | } 108 | std::cout << std::endl; 109 | return (0); 110 | } 111 | -------------------------------------------------------------------------------- /tests/alloc_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file alloc_test.cpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief allocator test 5 | * @version 0.1 6 | * @date 2022-03-28 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include <iostream> 13 | #include <memory> 14 | #include <vector> 15 | void allocTest(std::allocator<int> myAlloc, int **arr) { 16 | myAlloc.construct(*arr, 42412); 17 | myAlloc.construct(*arr + 1, 1); 18 | myAlloc.construct(*arr + 2, 1); 19 | myAlloc.destroy(*arr); 20 | // for (int i = 0; i < 2; i++) std::cout << sizeof(*arr[i]) << ","; 21 | // for (int i = 0; i < 2; i++) std::cout << *arr[i] << ","; 22 | } 23 | 24 | void test_init_is_heap() { 25 | // int *val = NULL; 26 | // my::uninitialized_fill(val, val + 7, 42); 27 | // return val; 28 | int b = 42; 29 | int c = b; 30 | int *val = ::new (static_cast<void *>(&c)) int(b); 31 | std::cout << *val; 32 | } 33 | 34 | template <typename T> 35 | void my_destroy(T t) { 36 | ~T(t); 37 | } 38 | 39 | class ipad { 40 | public: 41 | double *model; 42 | ipad() : model(new double[10]) { 43 | for (int i = 0; i < 10; i++) model[i] = i; 44 | } 45 | ipad(double d) : model(new double[10]) { 46 | for (int i = 0; i < 10; i++) model[i] = i + d; 47 | } 48 | ~ipad() { delete[] model; } 49 | }; 50 | 51 | std::ostream &operator<<(std::ostream &os, ipad &pad) { 52 | for (int i = 0; i < 10; i++) os << pad.model[i] << ", "; 53 | return os; 54 | } 55 | 56 | void rebind_test() { 57 | typedef std::allocator<int> _alloc; 58 | typedef _alloc::rebind<ipad>::other ipad_alloc; 59 | _alloc::rebind<ipad>::other dalloc2; 60 | ipad_alloc dalloc(dalloc2); 61 | ipad *darr = dalloc.allocate(10); 62 | for (int i = 0; i < 10; i++) dalloc.construct(darr + i, 4.242 + i); 63 | for (int i = 0; i < 10; i++) 64 | std::cout << i << ": " 65 | << "[" << darr[i] << "] "; 66 | std::cout << "\n"; 67 | for (int i = 0; i < 10; i++) dalloc.destroy(darr + i); 68 | for (int i = 0; i < 10; i++) std::cout << "[" << darr[i] << "] "; 69 | dalloc.deallocate(darr, 10); 70 | } 71 | 72 | int main() { 73 | rebind_test(); 74 | std::allocator<int> myAlloc; 75 | int *arr = myAlloc.allocate(14); 76 | myAlloc.construct(arr, 424242); 77 | my_destroy(*arr); 78 | std::cout << *arr << "\n"; 79 | allocTest(myAlloc, &arr); 80 | // std::vector<int> a(42, 10, myAlloc); 81 | // std::cout << sizeof(a); 82 | myAlloc.deallocate(arr, 1); 83 | std::cout << "\n"; 84 | 85 | // int *aa; 86 | // new (static_cast<void *>(aa)) int; 87 | 88 | // std::cout << *aa; 89 | // delete aa; 90 | { 91 | int arr[10]; 92 | std::uninitialized_fill(&arr[0], &arr[10], 42); 93 | std::cout << *arr << "\n"; 94 | } 95 | 96 | { test_init_is_heap(); } 97 | { 98 | try { 99 | std::vector<int> a(SIZE_MAX, 42); 100 | a.push_back(1002); 101 | } catch (...) { 102 | std::cout << "alloc error?\n"; 103 | } 104 | } 105 | 106 | // int *val = test_init_is_heap(); 107 | // for (int *tmp = val; tmp < val + 10; tmp++) { 108 | // std::cout << *tmp << ","; 109 | // } 110 | // myAlloc.deallocate(val, 1); 111 | system("leaks mine.out"); 112 | } -------------------------------------------------------------------------------- /tests/functor_test.cpp: -------------------------------------------------------------------------------- 1 | #include <algorithm> 2 | #include <iostream> 3 | #include <vector> 4 | 5 | struct Add { 6 | Add(int toAdd) : _toAdd(toAdd) {} 7 | int operator()(int x) { return x + _toAdd; } 8 | 9 | private: 10 | int _toAdd; 11 | }; 12 | 13 | template <typename pair> 14 | struct select_first { 15 | typename pair::first_type& operator()(pair& __x) const { return __x.first; } 16 | }; 17 | 18 | int main() { 19 | Add add_42(42); 20 | Add add_13(13); 21 | int result_42 = add_42(2); 22 | int result_13 = add_13(2); 23 | std::vector<int> v(10, 10); 24 | std::transform(v.begin(), v.end(), v.begin(), add_42); 25 | std::vector<int>::iterator it = v.begin(); 26 | std::vector<int>::iterator ite = v.end(); 27 | for (; it != ite; ++it) std::cout << "[" << *it << "]"; 28 | std::cout << "\n"; 29 | 30 | std::pair<int, std::string> pr(1, "abc"); 31 | std::cout << "[" << pr.first << "] [" << pr.second << "]\n"; 32 | std::cout << select_first<std::pair<int, std::string> >()(pr) << "\n"; 33 | // std::cout << select_first<int>()(pr) << "\n"; 34 | } -------------------------------------------------------------------------------- /tests/iterator_test.cpp: -------------------------------------------------------------------------------- 1 | #include <deque> 2 | #include <iostream> 3 | #include <iterator> 4 | #include <list> 5 | #include <map> 6 | #include <set> 7 | #include <vector> 8 | 9 | #include "test.hpp" 10 | 11 | template <typename tag> 12 | struct my { 13 | static const bool input = ft::__is_input_iterator<tag>::value; 14 | static const bool output = ft::__is_output_iterator<tag>::value; 15 | static const bool fwd = ft::__is_forward_iterator<tag>::value; 16 | static const bool bidi = ft::__is_bidirectional_iterator<tag>::value; 17 | static const bool rd = ft::__is_random_access_iterator<tag>::value; 18 | }; 19 | 20 | template <typename tag> 21 | std::ostream &operator<<(std::ostream &os, my<tag> in) { 22 | os << "input:" << in.input << ", output :" << in.output 23 | << ", forward :" << in.fwd << ", bidirectional :" << in.bidi 24 | << ", random access :" << in.rd; 25 | return os; 26 | } 27 | 28 | template <typename tag> 29 | struct lib { 30 | static const bool input = std::__is_cpp17_input_iterator<tag>::value; 31 | static const bool fwd = std::__is_cpp17_forward_iterator<tag>::value; 32 | static const bool bidi = std::__is_cpp17_bidirectional_iterator<tag>::value; 33 | static const bool rd = std::__is_cpp17_random_access_iterator<tag>::value; 34 | }; 35 | 36 | template <typename tag> 37 | std::ostream &operator<<(std::ostream &os, lib<tag> in) { 38 | os << "input:" << in.input << ", output :" 39 | << "N / A" 40 | << ", forward :" << in.fwd << ", bidirectional :" << in.bidi 41 | << ", random access :" << in.rd; 42 | return os; 43 | } 44 | 45 | void check_iterator_category() { 46 | my<ft::iterator<ft::input_iterator_tag, int> > my_in_tag; 47 | lib<std::iterator<std::input_iterator_tag, int> > lib_in_tag; 48 | my<ft::iterator<ft::output_iterator_tag, int> > my_out_tag; 49 | lib<std::iterator<std::output_iterator_tag, int> > lib_out_tag; 50 | my<ft::iterator<ft::forward_iterator_tag, int> > my_fwd_tag; 51 | lib<std::iterator<std::forward_iterator_tag, int> > lib_fwd_tag; 52 | my<ft::iterator<ft::bidirectional_iterator_tag, int> > my_bidi_tag; 53 | lib<std::iterator<std::bidirectional_iterator_tag, int> > lib_bidi_tag; 54 | my<ft::iterator<ft::random_access_iterator_tag, int> > my_rd_tag; 55 | lib<std::iterator<std::random_access_iterator_tag, int> > lib_rd_tag; 56 | 57 | bool test = ft::__is_input_iterator< 58 | ft::iterator<std::input_iterator_tag, int> >::value; 59 | // ft::__is_iterator< 60 | // ft::iterator<std::input_iterator_tag, int> >::iterator_category a; 61 | 62 | // std::iterator_traits<int> aa; 63 | ft::iterator_traits<int *> bb; 64 | 65 | std::cout << "====== input =====\n"; 66 | std::cout << "My ret -> " << my_in_tag << "\n"; 67 | std::cout << "lib ret -> " << lib_in_tag << "\n"; 68 | 69 | std::cout << "====== output =====\n"; 70 | std::cout << "My ret -> " << my_out_tag << "\n"; 71 | std::cout << "lib ret -> " << lib_out_tag << "\n"; 72 | 73 | std::cout << "====== forward =====\n"; 74 | std::cout << "My ret -> " << my_fwd_tag << "\n"; 75 | std::cout << "lib ret -> " << lib_fwd_tag << "\n"; 76 | 77 | std::cout << "====== bidirectional =====\n"; 78 | std::cout << "My ret -> " << my_bidi_tag << "\n"; 79 | std::cout << "lib ret -> " << lib_bidi_tag << "\n"; 80 | 81 | std::cout << "====== random_access =====\n"; 82 | std::cout << "My ret -> " << my_rd_tag << "\n"; 83 | std::cout << "lib ret -> " << lib_rd_tag << "\n"; 84 | } 85 | 86 | void simple_test() { 87 | std::iterator<int, int, int, int *, int *> a; 88 | std::cout << typeid(a).name() << "\n"; 89 | ft::iterator<int, int, int, int *, int *> b; 90 | std::cout << typeid(b).name() << "\n"; 91 | std::vector<int> vtest(10, 10); 92 | std::vector<int>::iterator it = vtest.begin(); 93 | std::cout << std::boolalpha 94 | << ft::is_same<std::vector<int>::pointer, 95 | std::vector<int>::iterator>::value; 96 | std::vector<int>::pointer t1; 97 | std::vector<int>::iterator t2; 98 | std::cout << typeid(t1).name() << "\n" << typeid(t2).name() << "\n"; 99 | typedef ft::iterator<ft::input_iterator_tag, int> my_it; 100 | // ft::reverse_iterator<my_it> rit; 101 | } 102 | 103 | template <typename U> 104 | static int __test(...) { 105 | std::cout << "!Q!! ... !!!\n"; 106 | return 2; 107 | } 108 | 109 | template <typename U> 110 | static char __test( 111 | typename ft::void_t<typename U::iterator_category>::type * = 0, 112 | typename ft::void_t<typename U::difference_type>::type * = 0, 113 | typename ft::void_t<typename U::value_type>::type * = 0, 114 | typename ft::void_t<typename U::pointer>::type * = 0, 115 | typename ft::void_t<typename U::reference>::type * = 0) { 116 | std::cout << "types!!!!!\n"; 117 | return 1; 118 | }; 119 | 120 | void iterable_test() { 121 | std::iterator<std::random_access_iterator_tag, float> f_it; 122 | // std::__has_iterator_category< 123 | // ft::iterator<ft::input_iterator_tag, float> >::value; 124 | ft::iterator<std::input_iterator_tag, float> ft_f_it; 125 | std::cout << ft::__has_iterator_typedefs< 126 | ft::iterator<std::input_iterator_tag, float> >::value 127 | << "\n"; 128 | // std::__has_iterator_typedefs< 129 | // ft::iterator<ft::input_iterator_tag, float> >::value; 130 | 131 | __test<ft::iterator<ft::input_iterator_tag, float> >(0, 0, 0, 0, 0); 132 | __test<int>(0, 0, 0, 0, 0); 133 | std::cout << sizeof(__test<ft::iterator<ft::input_iterator_tag, float> >( 134 | 0, 0, 0, 0, 0)) 135 | << " <- test size\n"; 136 | // ft::enable_if<f_it::iterator_catrgory>::type 137 | // ft::__iterator_traits< 138 | // ft::iterator<std::input_iterator_tag, float>, >::difference_type a = 1; 139 | } 140 | 141 | int main() { 142 | std::cout << "==== simple_test =====\n"; 143 | simple_test(); 144 | std::cout << "==== iterable_test =====\n"; 145 | iterable_test(); 146 | std::cout << "==== check_iterator_category =====\n"; 147 | check_iterator_category(); 148 | 149 | { 150 | // ft::iterator_traits<ft::__tree_const_iterator<int> >::value_type a; 151 | // ft::__tree_const_iterator<int>::value_type a; 152 | // ft::__tree_const_iterator<int>::difference_type b; 153 | // ft::__tree_const_iterator<int>::iterator_catergory c; 154 | // ft::__tree_const_iterator<int>::pointer d; 155 | // ft::__tree_const_iterator<int>::reference f = 10; 156 | // std::cout << typeid(a).name() << ", " << typeid(b).name() << ", " 157 | // << typeid(c).name() << ", " << typeid(d).name() << ", " 158 | // << typeid(f).name() << ", \n"; 159 | } 160 | __test<ft::vector<int>::iterator>(0, 0, 0, 0, 0); 161 | __test<ft::__tree_const_iterator<int> >(0, 0, 0, 0, 0); 162 | __test<ft::iterator_traits<ft::__tree_const_iterator<int> > >(0, 0, 0, 0, 0); 163 | int arr[5] = {1, 2, 5, 4, 3}; 164 | ft::pair<int, int> b[5]; 165 | std::pair<int, int> c[5]; 166 | for (int i = 0; i < 5; i++) { 167 | b[i] = ft::make_pair(arr[i], arr[i]); 168 | c[i] = std::make_pair(arr[i], arr[i]); 169 | } 170 | ft::map<int, int> mp(b, b + 5); 171 | std::map<int, int> smp(c, c + 5); 172 | ft::map<int, int>::iterator it = mp.begin(); 173 | std::map<int, int>::iterator sit = smp.begin(); 174 | // ft::map<int, int>::const_iterator cit = mp.begin(); 175 | // std::map<int, int>::const_iterator scit = smp.begin(); 176 | // *sit = std::make_pair(42, 42); 177 | // *it = ft::make_pair(42, 42); 178 | __test<ft::map<int, int>::const_iterator>(0, 0, 0, 0, 0); 179 | __test<ft::map<int, int>::const_reverse_iterator>(0, 0, 0, 0, 0); 180 | __test<ft::map<int, int>::reverse_iterator>(0, 0, 0, 0, 0); 181 | ft::map<int, int>::reverse_iterator rit(it); 182 | ft::map<int, int>::const_reverse_iterator crit(rit); 183 | // ft::map<int, int>::const_reverse_iterator crit_2(cit); 184 | // ft::iterator_traits<ft::__tree_const_iterator<int> >::value_type val; 185 | 186 | // std::cout << rit[5]; 187 | } -------------------------------------------------------------------------------- /tests/map_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.hpp" 2 | 3 | struct print { 4 | template <typename T> 5 | void operator()(T val) { 6 | std::cout << "key: " << val.first << ", value: " << val.second << "\n"; 7 | } 8 | }; 9 | 10 | void max_size_test() { 11 | ft::map<int, ft::vector<int> > my_map; 12 | size_t map_max = my_map.max_size(); 13 | std::cout << "ft max_size: " << map_max << "\n"; 14 | try { 15 | // for (size_t i = 0; i < map_max; ++i) { 16 | // my_map.insert(ft::make_pair(i, i)); 17 | // } 18 | my_map.get_allocator().allocate(map_max - 1); 19 | } catch (std::exception &e) { 20 | std::cout << "exception occur" << e.what() << "\n"; 21 | } 22 | 23 | std::map<int, ft::vector<int> > std_map; 24 | size_t std_map_max = std_map.max_size(); 25 | std::cout << "STD max_size: " << std_map_max << "\n"; 26 | try { 27 | std_map.get_allocator().allocate(std_map_max / 2); 28 | } catch (std::exception &e) { 29 | std::cout << "exception occur" << e.what() << "\n"; 30 | } 31 | std::cout << ft::set<int>().max_size() << "\n"; 32 | std::cout << std::set<int>().max_size() << "\n"; 33 | } 34 | 35 | void map_test(int argc, char **argv) { 36 | ft::map<char, int> my_map; 37 | std::map<char, int> std_map; 38 | for (int i = 0; argv[0][i]; ++i) { 39 | my_map.insert(ft::make_pair(argv[0][i], i)); 40 | std_map.insert(std::make_pair(argv[0][i], i)); 41 | } 42 | std::cout << (my_map.find('/'))->second << "\n"; 43 | ft::map<char, int>::iterator it = my_map.begin(); 44 | ft::map<char, int>::iterator ite = my_map.end(); 45 | std::for_each(it, ite, print()); 46 | std::for_each(std_map.begin(), std_map.end(), print()); 47 | std::cout << my_map.size() << ", " << my_map.max_size() << "\n"; 48 | std::cout << my_map.max_size() << ", " << std_map.max_size() << "\n"; 49 | std::cout << sizeof(my_map) << "," << sizeof(std_map) << "\n"; 50 | std::cout << sizeof(ft::__tree<int, int, ft::select_first<int> >) << "\n"; 51 | std::cout << sizeof(std::__tree<int, std::less<int>, std::allocator<int> >) 52 | << "\n"; 53 | ft::__tree_key_compare<std::less<int> > key_cmp; 54 | std::cout << "key comp : " << sizeof(key_cmp.__key_comp) << "\n"; 55 | } 56 | 57 | template <typename T> 58 | void print_iter(T it, T ite) { 59 | for (; it != ite; ++it) print()(*it); 60 | } 61 | 62 | void compare_test(int argc, char **argv) { 63 | std::cout << std::boolalpha; 64 | ft::map<int, std::string> a; 65 | ft::map<int, std::string> b; 66 | ft::pair<int, std::string> pr; 67 | for (int i = 0; i < argc; ++i) { 68 | pr = ft::make_pair(i, argv[i]); 69 | if (i != argc - 1) { 70 | b.insert(pr); 71 | } 72 | a.insert(pr); 73 | } 74 | PRINT("map a"); 75 | print_iter(a.begin(), a.end()); 76 | PRINT("map b"); 77 | print_iter(b.begin(), b.end()); 78 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 79 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 80 | a >= b); 81 | b.insert(pr); 82 | PRINT("map a"); 83 | print_iter(a.begin(), a.end()); 84 | PRINT("map b"); 85 | print_iter(b.begin(), b.end()); 86 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 87 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 88 | a >= b); 89 | b.erase(pr.first); 90 | PRINT("map a"); 91 | print_iter(a.begin(), a.end()); 92 | PRINT("map b"); 93 | print_iter(b.begin(), b.end()); 94 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 95 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 96 | a >= b); 97 | ++pr.first; 98 | b.insert(pr); 99 | PRINT("map a"); 100 | print_iter(a.begin(), a.end()); 101 | PRINT("map b"); 102 | print_iter(b.begin(), b.end()); 103 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 104 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 105 | a >= b); 106 | } 107 | 108 | int main(int argc, char **argv) { 109 | max_size_test(); 110 | map_test(argc, argv); 111 | compare_test(argc, argv); 112 | sizeof(ft::__tree_node_base); 113 | system("leaks mine.out"); 114 | } -------------------------------------------------------------------------------- /tests/pair_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.hpp" 2 | 3 | int main(int argc, char **argv) { 4 | std::cout << std::boolalpha; 5 | ft::pair<int, std::string> pr[argc]; 6 | for (int i = 0; i < argc; i++) 7 | pr[i] = ft::make_pair<int, std::string>(i, argv[i]); 8 | for (int i = 0; i < argc; i++) { 9 | PRINT("pair[", i, "] : (", pr[i].first, ", ", pr[i].second, ")"); 10 | } 11 | ft::pair<int, std::string> a(pr[0]); 12 | ft::pair<int, std::string> b(pr[0]); 13 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 14 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 15 | a >= b); 16 | b = pr[1]; 17 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 18 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 19 | a >= b); 20 | ft::vector<ft::pair<int, std::string> > v(pr, pr + argc); 21 | ft::vector<ft::pair<int, std::string> >::iterator it = v.begin(); 22 | ft::vector<ft::pair<int, std::string> >::iterator ite = v.end(); 23 | for (; it != ite; ++it) { 24 | std::cout << "[" << (*it).first << ", " << (*it).second << "] "; 25 | } 26 | std::cout << "\n"; 27 | } -------------------------------------------------------------------------------- /tests/raii_test.cpp: -------------------------------------------------------------------------------- 1 | #include <sys/errno.h> 2 | 3 | #include <cstdlib> 4 | #include <iostream> 5 | #include <memory> 6 | #include <vector> 7 | 8 | class thrw { 9 | protected: 10 | int *x; 11 | size_t size; 12 | std::allocator<int> a; 13 | 14 | public: 15 | thrw() : x(NULL), size(424242), a(std::allocator<int>()) { 16 | std::cout << "thrw constructor\n"; 17 | // leaks here ! 18 | // allocate_memory(); 19 | } 20 | void allocate_memory() { 21 | std::cout << "allocate_memory\n"; 22 | for (;;) { 23 | x = a.allocate(size); 24 | if (size > (a.max_size() >> 32)) throw std::bad_alloc(); 25 | a.deallocate(x, size); 26 | size *= 2; 27 | } 28 | } 29 | ~thrw() { 30 | std::cout << "thrw destructor\n"; 31 | a.deallocate(x, size); 32 | } 33 | }; 34 | 35 | class thrw_child : public thrw { 36 | public: 37 | thrw_child() : thrw() { 38 | std::cout << "thrw_child constructor\n"; 39 | allocate_memory(); 40 | } 41 | ~thrw_child() { std::cout << "thrw_child destructor\n"; } 42 | }; 43 | 44 | void raii_test() { 45 | thrw a; 46 | std::cout << "a constructed...\n"; 47 | a.allocate_memory(); 48 | } 49 | 50 | void raii_child_test() { thrw_child a; } 51 | 52 | int main() { 53 | try { 54 | raii_test(); 55 | } catch (std::exception &e) { 56 | std::cout << e.what() << " in Main raii_test CATCH\n"; 57 | } 58 | try { 59 | raii_child_test(); 60 | } catch (std::exception &e) { 61 | std::cout << e.what() << " in Main raii_child_test CATCH\n"; 62 | } 63 | system("leaks mine.out | grep leaked"); 64 | } -------------------------------------------------------------------------------- /tests/set_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.hpp" 2 | struct print { 3 | template <typename T> 4 | void operator()(T val) { 5 | std::cout << "key: " << val << "\n"; 6 | } 7 | }; 8 | 9 | void max_size_test() { 10 | ft::set<ft::vector<int> > my_set; 11 | size_t set_max = my_set.max_size(); 12 | std::cout << "ft max_size: " << set_max << "\n"; 13 | try { 14 | // for (size_t i = 0; i < set_max; ++i) { 15 | // my_set.insert(ft::make_pair(i, i)); 16 | // } 17 | my_set.get_allocator().allocate(set_max); 18 | } catch (std::exception &e) { 19 | std::cout << "exception occur" << e.what() << "\n"; 20 | } 21 | 22 | std::set<ft::vector<int> > std_set; 23 | size_t std_set_max = std_set.max_size(); 24 | std::cout << "STD max_size: " << std_set_max << "\n"; 25 | try { 26 | std_set.get_allocator().allocate(std_set_max >> 32); 27 | } catch (std::exception &e) { 28 | std::cout << "exception occur" << e.what() << "\n"; 29 | } 30 | { 31 | ft::set<int> my_int_set; 32 | std::set<int> std_int_set; 33 | for (int i = 0; i < 10000; i++) { 34 | my_int_set.insert(i); 35 | std_int_set.insert(i); 36 | } 37 | std::cout << my_int_set.max_size() << "\n"; 38 | std::cout << std_int_set.max_size() << "\n"; 39 | std::cout << ft::set<float>().max_size() << "\n"; 40 | std::cout << std::set<float>().max_size() << "\n"; 41 | } 42 | } 43 | 44 | void set_test(int argc, char **argv) { 45 | ft::set<std::string> my_set; 46 | std::set<std::string> std_set; 47 | for (int i = 0; i < argc; ++i) { 48 | my_set.insert(std::string(argv[i])); 49 | std_set.insert(std::string(argv[i])); 50 | } 51 | std::cout << *(my_set.find(argv[2])) << "\n"; 52 | ft::set<std::string>::iterator it = my_set.begin(); 53 | ft::set<std::string>::iterator ite = my_set.end(); 54 | std::for_each(it, ite, print()); 55 | std::for_each(std_set.begin(), std_set.end(), print()); 56 | std::cout << my_set.size() << ", " << my_set.max_size() << "\n"; 57 | std::cout << my_set.max_size() << ", " << std_set.max_size() << "\n"; 58 | std::cout << sizeof(my_set) << "," << sizeof(std_set) << "\n"; 59 | std::cout << sizeof(ft::__tree<int, int, ft::select_first<int> >) << "\n"; 60 | std::cout << sizeof(std::__tree<int, std::less<int>, std::allocator<int> >) 61 | << "\n"; 62 | ft::__tree_key_compare<std::less<int> > key_cmp; 63 | std::cout << "key comp : " << sizeof(key_cmp.__key_comp) << "\n"; 64 | } 65 | 66 | int main(int argc, char **argv) { 67 | max_size_test(); 68 | set_test(argc, argv); 69 | std::cout << std::numeric_limits<ptrdiff_t>().max() << "\n"; 70 | std::cout << std::numeric_limits<size_t>().max() << "\n"; 71 | std::cout << sizeof(std::__compressed_pair<size_t, std::allocator<int> >) 72 | << "\n"; 73 | std::cout << sizeof(ft::pair<size_t, std::allocator<int> >) << "\n"; 74 | std::cout << sizeof(std::pair<size_t, std::allocator<int> >) << "\n"; 75 | std::cout << sizeof(std::__compressed_pair<int, double>) << "\n"; 76 | std::cout << sizeof(ft::pair<int, double>) << "\n"; 77 | std::cout << sizeof(std::pair<int, double>) << "\n"; 78 | system("leaks mine.out"); 79 | } -------------------------------------------------------------------------------- /tests/stack_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.hpp" 2 | 3 | void method_test(int argc, char **argv) { 4 | ft::stack<std::string> stk; 5 | std::cout << std::boolalpha; 6 | PRINT("stk.empty :", stk.empty()); 7 | for (int i = 0; i < argc; i++) { 8 | PRINT("stk.push(", argv[i], ")"); 9 | stk.push(argv[i]); 10 | PRINT("stk.size() :", stk.size()); 11 | } 12 | PRINT("stk.empty :", stk.empty()); 13 | for (int i = 0; i < argc; i++) { 14 | PRINT("stk.top() : ", stk.top()); 15 | stk.pop(); 16 | } 17 | PRINT("stk.empty :", stk.empty()); 18 | } 19 | 20 | template <typename stack> 21 | void print_stack(stack &stk) { 22 | PRINT("stack (size, empty, top) (", stk.size(), ", ", stk.empty(), ", ", 23 | stk.top(), ")"); 24 | } 25 | 26 | void operator_test() { 27 | ft::stack<double> a; 28 | ft::stack<double> b; 29 | PRINT("push to stack a , b"); 30 | for (int i = 0; i < 10; i++) { 31 | a.push(4.2 + i); 32 | b.push(4.2 + i); 33 | std::cout << "[" << 4.2 + i << "] "; 34 | } 35 | std::cout << "\n"; 36 | PRINT("stack a"); 37 | print_stack(a); 38 | PRINT("stack b"); 39 | print_stack(b); 40 | PRINT("b.pop()"); 41 | b.pop(); 42 | PRINT("stack b"); 43 | print_stack(b); 44 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 45 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 46 | a >= b); 47 | PRINT("b.push(13.2)"); 48 | b.push(13.2); 49 | PRINT("stack a"); 50 | print_stack(a); 51 | PRINT("stack b"); 52 | print_stack(b); 53 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 54 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 55 | a >= b); 56 | PRINT("b.pop()"); 57 | b.pop(); 58 | PRINT("stack a"); 59 | print_stack(a); 60 | PRINT("stack b"); 61 | print_stack(b); 62 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 63 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 64 | a >= b); 65 | PRINT("b.push(13.2)"); 66 | b.push(13.2); 67 | PRINT("stack a"); 68 | print_stack(a); 69 | PRINT("stack b"); 70 | print_stack(b); 71 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 72 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 73 | a >= b); 74 | } 75 | 76 | int main(int argc, char **argv) { 77 | method_test(argc, argv); 78 | operator_test(); 79 | } -------------------------------------------------------------------------------- /tests/testtest.cpp: -------------------------------------------------------------------------------- 1 | #include <iostream> 2 | #include <string> 3 | 4 | #include "utility.hpp" 5 | 6 | class Parent { 7 | public: 8 | std::string a; 9 | Parent() { a = "a"; } 10 | void printA() { std::cout << a << "\n"; } 11 | }; 12 | class Child : public Parent { 13 | public: 14 | Child() { a = "b"; } 15 | }; 16 | 17 | class SwapTest { 18 | private: 19 | std::string str; 20 | 21 | public: 22 | SwapTest() : str("NULL") { std::cout << str << "SwapTest\n"; } 23 | SwapTest(std::string string) : str(string) { 24 | std::cout << str << "SwapTest\n"; 25 | } 26 | SwapTest(const SwapTest& oth) : str(oth.str) { 27 | std::cout << str << "SwapTest copy constructor\n"; 28 | } 29 | const SwapTest& operator=(const SwapTest& oth) { 30 | this->str = oth.str; 31 | std::cout << str << "Swap assign operator\n"; 32 | return *this; 33 | } 34 | std::string& get() { return str; } 35 | ~SwapTest() { std::cout << str << "SwapTest Destroyed\n"; } 36 | }; 37 | 38 | unsigned test() { return 3489589589132ULL; } 39 | 40 | // const method test. 41 | // call non-const to const function: ok 42 | // call const to non-const function: no!! 43 | template <typename T> 44 | class ConstTest { 45 | private: 46 | int a; 47 | 48 | public: 49 | typedef T my; 50 | typedef const T cmy; 51 | ConstTest() : a(0) {} 52 | my& print(my& val) const { 53 | std::cout << "print with my :" << val << "\n"; 54 | return val; 55 | } 56 | cmy& print(cmy& val) const { 57 | std::cout << "print with cmy :" << val << "\n"; 58 | return val; 59 | } 60 | }; 61 | int main() { 62 | Parent p; 63 | Child c; 64 | 65 | // Child *cc = new Parent; 66 | unsigned a = test(); 67 | std::cout << a << "\n"; 68 | std::cout << typeid(unsigned).name() << "," << typeid(unsigned int).name() 69 | << "\n"; 70 | { 71 | const int a = 42; 72 | int b = 4242; 73 | ConstTest<int> test; 74 | test.print(a); 75 | test.print(b); 76 | int c = 55; 77 | std::swap(c, b); 78 | } 79 | { 80 | SwapTest a("hi im a"); 81 | SwapTest b("hi im b"); 82 | std::cout << "before swap:\naddress of a: " << &a 83 | << "\naddress of b: " << &b << "\n"; 84 | ft::swap(a, b); 85 | std::cout << "after swap:\naddress of a: " << &a << "\naddress of b: " << &b 86 | << "\n"; 87 | // std::swap(a, b); 88 | std::cout << "a: " << a.get() << "\nb: " << b.get() << "\n"; 89 | std::cout << "===end swap ===\n"; 90 | } 91 | 92 | p.printA(); 93 | c.printA(); 94 | } 95 | -------------------------------------------------------------------------------- /tests/throw_test.cpp: -------------------------------------------------------------------------------- 1 | #include <sys/time.h> 2 | 3 | #include <iostream> 4 | int f2(int n); 5 | 6 | int f1(int n) { 7 | if (n == 42424) return n; 8 | return (f2(++n)); 9 | } 10 | 11 | int f2(int n) { 12 | f1(++n); 13 | return n; 14 | } 15 | 16 | int f3() throw() { return (f1(0)); } 17 | 18 | void throw_test() { 19 | try { 20 | struct timeval tp; 21 | gettimeofday(&tp, NULL); 22 | suseconds_t begin = tp.tv_usec; 23 | std::cout << tp.tv_sec << ":" << tp.tv_usec << "\n"; 24 | int n = f3(); 25 | gettimeofday(&tp, NULL); 26 | suseconds_t end = tp.tv_usec; 27 | std::cout << tp.tv_sec << ":" << tp.tv_usec << "\n"; 28 | std::cout << n; 29 | std::cout << "\nresult : " << end - begin << "\n"; 30 | } catch (...) { 31 | std::cout << "don't print\n"; 32 | } 33 | } 34 | 35 | int main() { throw_test(); } -------------------------------------------------------------------------------- /tests/tree_test.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "__tree.hpp" 3 | #include "test.hpp" 4 | 5 | #define R "\033[31m"; 6 | #define B "\033[32m"; 7 | #define RESET "\033[0m" 8 | 9 | typedef ft::__tree< 10 | int, ft::pair<int, std::string>, 11 | ft::select_first<ft::pair<int, std::string> >, std::less<int>, 12 | std::allocator<ft::pair<int, std::string> > >::iterator iterator; 13 | typedef ft::__tree<int, ft::pair<int, std::string>, 14 | ft::select_first<ft::pair<int, std::string> >, 15 | std::less<int>, std::allocator<ft::pair<int, std::string> > > 16 | my_tree; 17 | typedef ft::__tree<int, int, ft::identity<int>, std::less<int>, 18 | std::allocator<int> > 19 | int_tree; 20 | 21 | int_tree tree_int; 22 | 23 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 24 | typename _Alloc> 25 | void ft::__tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::print_tree() { 26 | print_tree("", __begin(), false); 27 | } 28 | 29 | template <typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, 30 | typename _Alloc> 31 | void ft::__tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::print_tree( 32 | const std::string &prefix, _Link_type x, bool isLeft) { 33 | if (x != NULL) { 34 | std::cout << prefix; 35 | std::cout << (isLeft ? "L├──" : "R└──"); 36 | if (x->__color_ == RED) { 37 | std::cout << R std::cout << __S_key(x) << RESET << "\n"; 38 | } else { 39 | std::cout << B std::cout << __S_key(x) << RESET << "\n"; 40 | } 41 | print_tree(prefix + (isLeft ? " │ " : " "), 42 | static_cast<_Link_type>(x->__left_), true); 43 | print_tree(prefix + (isLeft ? " │ " : " "), 44 | static_cast<_Link_type>(x->__right_), false); 45 | } 46 | } 47 | 48 | int generateRandomNumber(std::pair<int, int> range) { 49 | static bool first = true; 50 | if (first) { 51 | struct timeval tp; 52 | gettimeofday(&tp, NULL); 53 | srand(tp.tv_usec); 54 | rand(); 55 | first = false; 56 | } 57 | return ((static_cast<float>(rand())) / RAND_MAX) * 58 | (static_cast<long long>(range.second) - range.first + 1) + 59 | range.first; 60 | } 61 | int generateRandomNumber(int beg, int end) { 62 | static bool first = true; 63 | if (first) { 64 | struct timeval tp; 65 | gettimeofday(&tp, NULL); 66 | srand(tp.tv_usec); 67 | rand(); 68 | first = false; 69 | } 70 | return ((static_cast<float>(rand())) / RAND_MAX) * 71 | (static_cast<long long>(end) - beg + 1) + 72 | first; 73 | } 74 | 75 | void tree_test(int argc, char **argv) { 76 | argc *= 10; 77 | typedef ft::pair<int, std::string> _Val; 78 | ft::pair<int, std::string> test[argc]; 79 | for (int i = 0; i < argc; ++i) { 80 | test[i] = ft::make_pair(i, std::string(argv[0])); 81 | if (i == 10) test[i] = ft::make_pair(i, std::string("HI Im Val")); 82 | } 83 | { 84 | my_tree tree; 85 | tree.insert_range(test, test + argc); 86 | my_tree cptree(tree); 87 | my_tree atr; 88 | atr = tree; 89 | iterator it_test = tree.begin(); 90 | iterator ite_test = tree.end(); 91 | for (; it_test != ite_test; ++it_test) { 92 | std::cout << (*it_test).first << ", " << (*it_test).second << "\n"; 93 | } 94 | std::cout << "\n"; 95 | 96 | tree.print_tree(); 97 | std::cout << "tree size is: " << tree.size() << "\n"; 98 | std::cout << "delete random [" << argc / 3 << "] numbers of node\n"; 99 | 100 | for (int i = 1; i < (argc / 2); i++) { 101 | int num = generateRandomNumber(std::make_pair(0, argc)); 102 | std::cout << "Key to delete: " << num << "\n"; 103 | tree.erase(num); 104 | tree.print_tree(); 105 | } 106 | tree.print_tree(); 107 | cptree.print_tree(); 108 | atr.print_tree(); 109 | for (int i = 0; i < argc; ++i) { 110 | test[i] = 111 | ft::make_pair(generateRandomNumber(std::make_pair(-10000, 10000)), 112 | std::string(argv[0])); 113 | if (i == 10) test[i] = ft::make_pair(i, std::string("HI Im Val")); 114 | } 115 | tree.insert_range(test, test + argc); 116 | tree.print_tree(); 117 | std::cout << "tree size is: " << tree.size() << "\n"; 118 | iterator it = tree.find(10); 119 | if (it != tree.end()) std::cout << (*it).first << ":" << it->second << "\n"; 120 | it = tree.find(9); 121 | if (it != tree.end()) std::cout << (*it).first << ":" << it->second << "\n"; 122 | } 123 | { 124 | ft::__tree_node_base *basis = new ft::__tree_node_base[10]; 125 | for (int i = 0; i < 10; i++) { 126 | if (i & 1) 127 | basis[i].__color_ = ft::BLACK; 128 | else 129 | basis[i].__color_ = ft::RED; 130 | // std::cout << basis[i].__color_ << "\n"; 131 | } 132 | delete[] basis; 133 | } 134 | { 135 | ft::__tree_node<int> *test = new ft::__tree_node<int>(); 136 | int *val_ptr = test->__valptr(); 137 | *val_ptr = 42; 138 | // std::cout << &test.__value_field << "\n"; 139 | // std::cout << test->__valptr() << "\n"; 140 | // std::cout << test->__value_field << "\n"; 141 | delete test; 142 | } 143 | 144 | { 145 | // typedef std::allocator<_Val>::rebind<ft::__tree_node<_Val> >::other 146 | // _Node_alloc; 147 | // ft::__tree_node<_Val> *p = _Node_alloc().allocate(10); 148 | // std::uninitialized_fill(p, p + 10, 0); 149 | // _Node_alloc().destroy(p); 150 | // _Node_alloc().deallocate(p, 10); 151 | } 152 | 153 | // tree.insert_range(test, test + argc); 154 | } 155 | 156 | class why { 157 | private: 158 | int w; 159 | int h; 160 | int y; 161 | 162 | public: 163 | why() : w('w'), h('h'), y('y') {} 164 | }; 165 | 166 | template <typename _T, typename _Val, typename _Alloc = std::allocator<_T> > 167 | class AllocRebind { 168 | typedef typename _Alloc::template rebind<_Val>::other Node_Alloc; 169 | 170 | struct impl : public Node_Alloc, public why { 171 | impl() : Node_Alloc() {} 172 | }; 173 | 174 | public: 175 | impl _impl; 176 | AllocRebind() : _impl() {} 177 | Node_Alloc &get_node_alloc() { return this->_impl; } 178 | }; 179 | 180 | void alloc_test() { 181 | typedef ft::pair<int, std::string> value; 182 | AllocRebind<int, value> a; 183 | std::allocator<value> no = a.get_node_alloc(); 184 | value *pr = no.allocate(1); 185 | no.construct(pr, value(42, "42")); 186 | // std::cout << typeid(no).name() << "\n"; 187 | no.deallocate(pr, 1); 188 | } 189 | 190 | class static_test { 191 | public: 192 | static int S_increment() { 193 | int a = 0; 194 | for (int i = 0; i < 100000; i++) { 195 | if (i & 1) 196 | a++; 197 | else 198 | a -= 2; 199 | } 200 | return a; 201 | } 202 | int increment() { 203 | int a = 0; 204 | for (int i = 0; i < 100000; i++) { 205 | if (i & 1) 206 | a++; 207 | else 208 | a -= 2; 209 | } 210 | return a; 211 | } 212 | }; 213 | 214 | void benchmark_static() { 215 | timeval tp; 216 | suseconds_t tm1, tm2, gap1, gap2; 217 | 218 | gettimeofday(&tp, NULL); 219 | tm1 = tp.tv_usec; 220 | int b = static_test::S_increment(); 221 | // int c = static_test().increment(); 222 | gettimeofday(&tp, NULL); 223 | gap1 = tp.tv_usec - tm1; 224 | 225 | gettimeofday(&tp, NULL); 226 | tm2 = tp.tv_usec; 227 | int c = static_test().increment(); 228 | gettimeofday(&tp, NULL); 229 | gap2 = tp.tv_usec - tm2; 230 | 231 | std::cout << "static gap: " << gap1 << "\n" 232 | << "non-static gap: " << gap2 << "\n"; 233 | } 234 | 235 | #define GEN_NUM 100 236 | int main(int argc, char **argv) { 237 | // tree_test(argc, argv); 238 | // alloc_test(); 239 | // benchmark_static(); 240 | ft::vector<int> numbers; 241 | for (int i = 0; i < GEN_NUM; ++i) 242 | numbers.push_back(generateRandomNumber(std::make_pair(0, GEN_NUM * 3))); 243 | // int_tree tree_int; 244 | tree_int.insert_range(numbers.begin(), numbers.end()); 245 | tree_int.print_tree(); 246 | for (int j = 0; j < 5; ++j) { 247 | int i = generateRandomNumber(0, GEN_NUM - 1); 248 | std::cout << "to erase: " << numbers[i] << "\n"; 249 | tree_int.erase(numbers[i]); 250 | tree_int.print_tree(); 251 | } 252 | // tree_int.print_tree(); 253 | // tree_int.print_tree(); 254 | 255 | // int b = static_test::S_increment(); 256 | // int c = static_test().increment(); 257 | // 258 | // std::string leak = std::string("leaks ") + std::string(argv[0]); 259 | // system("leaks mine.out 1>/dev/null"); 260 | } 261 | -------------------------------------------------------------------------------- /tests/type_traits.cpp: -------------------------------------------------------------------------------- 1 | #include "type_traits.hpp" 2 | 3 | #include <deque> 4 | #include <iostream> 5 | #include <memory> 6 | #include <type_traits> 7 | #include <typeinfo> 8 | #include <vector> 9 | 10 | // 1번 후보 11 | template <typename Iter> 12 | typename Iter::value_type mean(Iter first, Iter last) { 13 | std::cout << "first candidate\n"; 14 | return *first; 15 | } 16 | 17 | // 2번 후보 18 | template <typename T> 19 | T mean(T* first, T* last) { 20 | std::cout << "second candidate\n"; 21 | return *first; 22 | } 23 | 24 | double mean(float a, char* b) { return 1.0; } 25 | 26 | void f(std::vector<int>& v, int* p, int n) { 27 | int x = mean(v.begin(), v.end()); // OK 28 | std::cout << x << "\n"; 29 | int a = mean(p, p + n); // error -> int*::value_type 꼴이 되어서 에러 -> 30 | // SFINAE에 의해 후보 2번을 찾아감 31 | std::cout << a << "\n"; 32 | } 33 | 34 | template <typename T> 35 | T* allocate(size_t size) throw(int) { 36 | throw 1; 37 | return new T[size]; 38 | } 39 | 40 | void sifae_test() { 41 | std::vector<int> v(10, 10); 42 | v.push_back(1); 43 | int* p = new int[10]; 44 | std::uninitialized_fill(p, p + 10, 42); 45 | int n = 5; 46 | f(v, p, n); 47 | try { 48 | int* throwing = allocate<int>(ULLONG_MAX); 49 | } catch (int n) { 50 | std::cout << n << "\n"; 51 | } catch (...) { 52 | std::cout << "thrown\n"; 53 | } 54 | } 55 | 56 | void integral_constant_test() { 57 | /** 58 | * @details This block does not work because variable a evaluate in run-time 59 | * int a = 10; 60 | * typedef std::integral_constant<int, a> std_two_t; 61 | * typedef ft::integral_constant<int, a> ft_two_t; 62 | **/ 63 | const size_t a = -1; 64 | typedef std::integral_constant<size_t, a> std_two_t; 65 | typedef ft::integral_constant<size_t, a> ft_two_t; 66 | if (ft_two_t::value == std_two_t::value) 67 | std::cout << "ft_two :" << ft_two_t() << "\n"; 68 | else { 69 | std::cout << "ft_two :" << ft_two_t() << "\n"; 70 | std::cout << "std_two :" << std_two_t() << "\n"; 71 | } 72 | std::cout << std::boolalpha << ft::true_type() << "\n"; 73 | std::cout << std::boolalpha << std::true_type() << "\n"; 74 | } 75 | template <int N> 76 | struct Factorial { 77 | static const int result = N * Factorial<N - 1>::result; 78 | }; 79 | 80 | template <> 81 | struct Factorial<1> { 82 | static const int result = 1; 83 | }; 84 | 85 | void calculate_based_type_eg() { 86 | typedef Factorial<10> ten; 87 | std::cout << "Factorial :" << ten::result << "\n"; 88 | }; 89 | 90 | template <typename T> 91 | void print_integral_test(T v) { 92 | std::cout << "current type is :" << typeid(v).name() << "\n"; 93 | std::cout << "std::is_integral :" << std::is_integral<T>() << "\n"; 94 | std::cout << "ft::is_integral :" << ft::is_integral<T>() << "\n"; 95 | } 96 | 97 | void is_integral_test() { 98 | print_integral_test(true); 99 | { 100 | signed char a = 'a'; 101 | print_integral_test(a); 102 | } 103 | { 104 | char a = 'a'; 105 | print_integral_test(a); 106 | } 107 | { 108 | unsigned char a = 'a'; 109 | print_integral_test(a); 110 | } 111 | { 112 | short a = 'a'; 113 | print_integral_test(a); 114 | } 115 | { 116 | unsigned short a = 'a'; 117 | print_integral_test(a); 118 | } 119 | { 120 | int a = 'a'; 121 | print_integral_test(a); 122 | } 123 | { 124 | unsigned int a = 'a'; 125 | print_integral_test(a); 126 | } 127 | { 128 | long a = 'a'; 129 | print_integral_test(a); 130 | } 131 | { 132 | unsigned long a = 'a'; 133 | print_integral_test(a); 134 | } 135 | { 136 | long long a = 'a'; 137 | print_integral_test(a); 138 | } 139 | { 140 | unsigned long long a = 'a'; 141 | print_integral_test(a); 142 | } 143 | { 144 | std::string a = "abc"; 145 | print_integral_test(a); 146 | } 147 | print_integral_test(1.0f); 148 | print_integral_test(1.0); 149 | std::vector<int> test(10, 10); 150 | print_integral_test(test); 151 | } 152 | 153 | void is_same_test() { 154 | std::cout << ft::is_same<int, double>::value << ", " 155 | << std::is_same<int, double>::value << "\n"; 156 | std::cout << ft::is_same<unsigned int, u_int32_t>::value << ", " 157 | << std::is_same<unsigned int, u_int32_t>::value << "\n"; 158 | std::cout << ft::is_same<std::vector<int>, std::vector<int> >::value << ", " 159 | << std::is_same<std::vector<int>, std::vector<int> >::value << "\n"; 160 | std::cout << ft::is_same<std::vector<int>, std::deque<int> >::value << ", " 161 | << std::is_same<std::vector<int>, std::deque<int> >::value << "\n"; 162 | std::cout << ft::is_same<std::vector<double>, std::vector<int> >::value 163 | << ", " 164 | << std::is_same<std::vector<double>, std::vector<int> >::value 165 | << "\n"; 166 | } 167 | 168 | int main() { 169 | std::cout << "===== SIFAE_TEST ===== \n"; 170 | sifae_test(); 171 | std::cout << "===== calculate_based_type_example ===== \n"; 172 | calculate_based_type_eg(); 173 | std::cout << "===== integral_constant_test ===== \n"; 174 | integral_constant_test(); 175 | std::cout << "===== is_integral_test ===== \n"; 176 | is_integral_test(); 177 | std::cout << "===== is_same_test ===== \n"; 178 | is_same_test(); 179 | } -------------------------------------------------------------------------------- /tests/vector_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file vector_main.cpp 3 | * @author yongjule (lyjshow200@gmail.com) 4 | * @brief How vector works? 5 | * @version 0.1 6 | * @date 2022-03-27 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include <fstream> 13 | 14 | #include "test.hpp" 15 | 16 | template <typename T> 17 | void print_vector(T it, T ite) { 18 | while (it != ite) { 19 | std::cout << *it << ", "; 20 | ++it; 21 | if (it == ite) std::cout << "\n"; 22 | } 23 | } 24 | 25 | template <typename vec> 26 | void print_vector(vec &v) { 27 | PRINT("vector info (size, capacity) : (", v.size(), ", ", v.capacity(), ")"); 28 | } 29 | 30 | void stl_method_test() { 31 | typedef std::vector<int>::iterator iterator; 32 | 33 | { 34 | std::cout << "swap()\n"; 35 | std::vector<int> x(10, 10); 36 | std::vector<int>().swap(x); // ??????????? 이런걸 왜하지? 37 | std::cout << "x capacity and size : " << x.capacity() << "," << x.size() 38 | << "\n"; 39 | } 40 | 41 | { 42 | std::cout << "insert()\n"; 43 | std::vector<int> a(10, 10); 44 | iterator it = a.begin() + 1; 45 | iterator it_insert = a.insert(it + 5, 42); 46 | std::cout << "insert ret location is: " 47 | << std::distance(a.begin(), it_insert) << "\n"; 48 | iterator itb = a.begin(); 49 | for (; itb != a.end(); itb++) std::cout << *itb << ","; 50 | std::cout << "\n"; 51 | int arr[] = {4242, 4241, 4240, 420, 424242}; 52 | a.insert(a.end(), arr, arr + 5); 53 | itb = a.begin(); 54 | for (; itb != a.end(); itb++) std::cout << *itb << ","; 55 | std::cout << "\n"; 56 | iterator it_erased = a.erase(a.end() - 4, a.end() - 1); 57 | std::cout << "*it_erased : " << *it_erased 58 | << "\n"; // end()의 위치이면, sanitize=address 걸면 터짐! 59 | std::cout << "distance(a.begin(), it_erased): " 60 | << std::distance(a.begin(), it_erased) << "\n"; 61 | itb = a.begin(); 62 | for (; itb != a.end(); itb++) std::cout << *itb << ","; 63 | std::cout << "\n"; 64 | } 65 | { 66 | std::cout << "front and back test when empty\n"; 67 | std::vector<int> a; 68 | std::cout << "vecot default capacity : " << a.capacity() << "\n"; 69 | try { 70 | std::cout << a.at(0) << "\n"; 71 | } catch (std::exception &e) { 72 | std::cout << "vector at :" << e.what() << "\n"; 73 | std::cout << typeid(e).name() << "\n"; 74 | } 75 | std::cout << "is empty? : " << a.empty() << "\n"; 76 | // std::cout << "a (front, back) : (" << a.front() << ", " << a.back() 77 | // << ")\n"; 78 | } 79 | } 80 | 81 | void my_vec_method_test() { 82 | // typedef ft::vector<int>::iterator iterator; 83 | { 84 | std::cout << "push_back()\n"; 85 | int arr[] = {4, 2, 42, 424, 242, 4242, 2424, 424242, 242424}; 86 | ft::vector<int> my_v(arr, arr + (sizeof(arr) / sizeof(int))); 87 | print_vector(my_v.begin(), my_v.end()); 88 | for (int i = 0; i < 420; i++) my_v.push_back(-4242); 89 | print_vector(my_v.begin(), my_v.end()); 90 | print_vector(my_v); 91 | } 92 | } 93 | 94 | void std_vec_method_test() { 95 | // typedef ft::vector<int>::iterator iterator; 96 | { 97 | std::cout << "push_back()\n"; 98 | int arr[] = {4, 2, 42, 424, 242, 4242, 2424, 424242, 242424}; 99 | std::vector<int> my_v(arr, arr + (sizeof(arr) / sizeof(int))); 100 | print_vector(my_v.begin(), my_v.end()); 101 | for (int i = 0; i < 420; i++) my_v.push_back(-4242); 102 | print_vector(my_v.begin(), my_v.end()); 103 | print_vector(my_v); 104 | } 105 | } 106 | 107 | void performance_test() { 108 | struct timeval tv; 109 | std::cout << "===== my_vec_method_test() =====\n"; 110 | gettimeofday(&tv, NULL); 111 | suseconds_t beg = tv.tv_usec; 112 | my_vec_method_test(); 113 | gettimeofday(&tv, NULL); 114 | suseconds_t taken = tv.tv_usec - beg; 115 | std::cout << "===== std_vec_method_test() =====\n"; 116 | gettimeofday(&tv, NULL); 117 | suseconds_t beg2 = tv.tv_usec; 118 | std_vec_method_test(); 119 | gettimeofday(&tv, NULL); 120 | suseconds_t taken2 = tv.tv_usec - beg2; 121 | 122 | std::cout << "ft::vector : <" << taken << "> std::vector : <" << taken2 123 | << ">\n"; 124 | std::cout << "ft is faster than std? :" << (taken < taken2) << "\n"; 125 | } 126 | 127 | class alloc_ed { 128 | private: 129 | int *a; 130 | 131 | public: 132 | alloc_ed() : a(new int[24]()) { 133 | std::cout << "constructer called\n"; 134 | for (int i = 0; i < 24; i++) a[i] = i * 2; 135 | } 136 | ~alloc_ed() { 137 | std::cout << "destructor called\n"; 138 | delete[] a; 139 | } 140 | }; 141 | 142 | void erase_test() { 143 | { 144 | std::cout << "std vector erase test\n"; 145 | std::vector<int> v(10, 10); 146 | v[5] = 421; 147 | v.push_back(42); 148 | std::cout << "erase from end -> seg fault\n"; 149 | std::vector<int>::iterator it = v.begin(); 150 | std::cout << "before erase: capacity :" << v.capacity() << "\n"; 151 | v.erase(v.begin() + 5); 152 | std::cout << "after erase: capacity :" << v.capacity() << "\n"; 153 | std::cout << "erased\n"; 154 | print_vector(v.begin(), v.end()); 155 | } 156 | 157 | { 158 | std::cout << "ft vector erase test\n"; 159 | ft::vector<int> v(10, 10); 160 | v[5] = 421; 161 | v.push_back(42); 162 | std::cout << "erase from end -> seg fault\n"; 163 | ft::vector<int>::iterator it = v.begin(); 164 | std::cout << "before erase: capacity :" << v.capacity() << "\n"; 165 | v.erase(v.begin() + 5); 166 | std::cout << "after erase: capacity :" << v.capacity() << "\n"; 167 | std::cout << "erased\n"; 168 | print_vector(v.begin(), v.end()); 169 | } 170 | 171 | { 172 | std::cout 173 | << "std vector alloc_ed class test\n"; // ????????? vector 가 터지네? 174 | std::vector<int> a; 175 | a.push_back(421); 176 | a.push_back(422); 177 | a.push_back(423); 178 | // a.pop_back(); 179 | a.erase(a.begin() + 1); 180 | print_vector(a.begin(), a.end()); 181 | // std::cout << "erase begin() + 5\n"; 182 | } 183 | 184 | { 185 | std::cout << "ft vector alloc_ed class test\n"; 186 | ft::vector<int> a; 187 | std::cout << "push_back\n"; 188 | a.push_back(421); 189 | a.push_back(422); 190 | a.push_back(423); 191 | // a.pop_back(); 192 | std::cout << "erase\n"; 193 | a.erase(a.begin() + 1); 194 | print_vector(a.begin(), a.end()); 195 | } 196 | { 197 | std::cout << "std vector range erase test\n"; 198 | std::string a[10] = {"a", "b", "c", "d", "e", "f"}; 199 | std::vector<std::string> v(a, a + 5); 200 | print_vector(v.begin(), v.end()); 201 | print_vector(v); 202 | v.erase(v.begin() + 1, v.end() - 2); 203 | print_vector(v.begin(), v.end()); 204 | print_vector(v); 205 | } 206 | { 207 | std::cout << "ft vector range erase test\n"; 208 | std::string a[10] = {"a", "b", "c", "d", "e", "f", "g"}; 209 | ft::vector<std::string> v(a, a + 7); 210 | print_vector(v.begin(), v.end()); 211 | print_vector(v); 212 | v.erase(v.begin(), v.begin() + 3); 213 | print_vector(v.begin(), v.end()); 214 | print_vector(v); 215 | } 216 | } 217 | 218 | void insert_test() { 219 | { 220 | typedef std::vector<int>::iterator iterator; 221 | PRINT("std vector insert()"); 222 | std::vector<int> a(10, 10); 223 | iterator it = a.begin() + 1; 224 | iterator it_insert = a.insert(it + 5, 10, 42); 225 | std::cout << "insert ret location is: " 226 | << std::distance(a.begin(), it_insert) << "\n"; 227 | print_vector(a.begin(), a.end()); 228 | print_vector(a); 229 | int arr[] = {4242, 4241, 4240, 420, 424242}; 230 | a.insert(a.end(), arr, arr + 5); 231 | print_vector(a.begin(), a.end()); 232 | print_vector(a); 233 | } 234 | 235 | { 236 | typedef ft::vector<int>::iterator iterator; 237 | PRINT("ft vector insert()"); 238 | ft::vector<int> a(10, 10); 239 | // a.insert(a.begin() + 2, a.begin(), a.end()); 240 | print_vector(a.begin(), a.end()); 241 | a.insert(a.end(), 424242); 242 | print_vector(a.begin(), a.end()); 243 | print_vector(a); 244 | a.insert(a.begin(), 42424211); 245 | print_vector(a.begin(), a.end()); 246 | print_vector(a); 247 | a.insert(a.begin() + 2, 424211); 248 | print_vector(a.begin(), a.end()); 249 | print_vector(a); 250 | a.insert(a.begin(), 2, 212121); 251 | print_vector(a.begin(), a.end()); 252 | print_vector(a); 253 | a.insert(a.end() - 2, 4242); 254 | print_vector(a.begin(), a.end()); 255 | print_vector(a); 256 | a.insert(a.end(), 2, 8484); 257 | print_vector(a.begin(), a.end()); 258 | print_vector(a); 259 | 260 | a.insert(a.begin() + 2, a.begin(), a.end()); 261 | print_vector(a.begin(), a.end()); 262 | print_vector(a); 263 | int arr[] = {4242, 4241, 4240, 420, 424242}; 264 | a.insert(a.end(), arr, arr + 5); 265 | print_vector(a.begin(), a.end()); 266 | print_vector(a); 267 | 268 | ft::vector<int> v2(5, 42); 269 | a.insert(a.begin() + 2, v2.begin(), v2.end()); 270 | print_vector(a.begin(), a.end()); 271 | } 272 | } 273 | 274 | void vector_construct_test() { 275 | { 276 | PRINT("ft::vector<int> v(3);"); 277 | ft::vector<int> v(3); 278 | print_vector(v.begin(), v.end()); 279 | print_vector(v); 280 | } 281 | 282 | { 283 | PRINT("ft::vector<int> v(3, 42);"); 284 | ft::vector<int> v(3, 42); 285 | print_vector(v.begin(), v.end()); 286 | print_vector(v); 287 | } 288 | 289 | { 290 | int arr[] = {42, 43, 44, 45}; 291 | PRINT("ft::vector<int> v(arr, arr + 4);"); 292 | ft::vector<int> v(arr, arr + 4); 293 | print_vector(v.begin(), v.end()); 294 | print_vector(v); 295 | 296 | PRINT("ft::vector<int> v_cp(v);"); 297 | ft::vector<int> v_cp(v); 298 | print_vector(v_cp.begin(), v_cp.end()); 299 | print_vector(v_cp); 300 | PRINT("copied memory :", &(*v_cp.begin()), "\n", 301 | "origin memory :", &(*v.begin())); 302 | } 303 | 304 | { 305 | PRINT( 306 | "ft::vector<char> v((std::istreambuf_iterator<char>(source)), " 307 | "std::istreambuf_iterator<char>()) "); 308 | std::ifstream source("Makefile", std::ios::binary); 309 | ft::vector<char> v((std::istreambuf_iterator<char>(source)), 310 | std::istreambuf_iterator<char>()); 311 | print_vector(v.begin(), v.end()); 312 | print_vector(v); 313 | } 314 | 315 | { 316 | ft::vector<char> v; 317 | std::ifstream source("Makefile", std::ios::binary); 318 | // v.assign(std::istreambuf_iterator<char>(source), 319 | // std::istreambuf_iterator<char>()); 320 | // print_vector(v.begin(), v.end()); 321 | // print_vector(v); 322 | } 323 | } 324 | 325 | void swap_test() { 326 | ft::vector<std::string> x; 327 | x.push_back("this"); 328 | x.push_back("is"); 329 | x.push_back("x"); 330 | PRINT("x"); 331 | PRINT(&(*x.begin()), "\n", &(*x.end()), "\n"); 332 | print_vector(x.begin(), x.end()); 333 | print_vector(x); 334 | ft::vector<std::string> y; 335 | y.push_back("this"); 336 | y.push_back("is"); 337 | y.push_back("y"); 338 | y.push_back("hahaha"); 339 | PRINT("Y"); 340 | PRINT(&(*y.begin()), "\n", &(*y.end()), "\n"); 341 | print_vector(y.begin(), y.end()); 342 | print_vector(y); 343 | x.swap(y); 344 | PRINT("x"); 345 | PRINT(&(*x.begin()), "\n", &(*x.end()), "\n"); 346 | print_vector(x.begin(), x.end()); 347 | print_vector(x); 348 | PRINT("Y"); 349 | PRINT(&(*y.begin()), "\n", &(*y.end()), "\n"); 350 | print_vector(y.begin(), y.end()); 351 | print_vector(y); 352 | ft::swap(x, y); 353 | PRINT("x"); 354 | PRINT(&(*x.begin()), "\n", &(*x.end()), "\n"); 355 | print_vector(x.begin(), x.end()); 356 | print_vector(x); 357 | PRINT("Y"); 358 | PRINT(&(*y.begin()), "\n", &(*y.end()), "\n"); 359 | print_vector(y.begin(), y.end()); 360 | print_vector(y); 361 | PRINT("assign operator test"); 362 | x = y; 363 | PRINT("x"); 364 | PRINT(&(*x.begin()), "\n", &(*x.end()), "\n"); 365 | print_vector(x.begin(), x.end()); 366 | print_vector(x); 367 | PRINT("Y"); 368 | PRINT(&(*y.begin()), "\n", &(*y.end()), "\n"); 369 | print_vector(y.begin(), y.end()); 370 | print_vector(y); 371 | } 372 | 373 | void compare_test() { 374 | ft::vector<double> a(10, 4.2); 375 | ft::vector<double> b(9, 4.2); 376 | PRINT("vector a"); 377 | print_vector(a.begin(), a.end()); 378 | PRINT("vector b"); 379 | print_vector(b.begin(), b.end()); 380 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 381 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 382 | a >= b); 383 | b.push_back(4.2); 384 | PRINT("vector a"); 385 | print_vector(a.begin(), a.end()); 386 | PRINT("vector b"); 387 | print_vector(b.begin(), b.end()); 388 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 389 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 390 | a >= b); 391 | b.pop_back(); 392 | PRINT("vector a"); 393 | print_vector(a.begin(), a.end()); 394 | PRINT("vector b"); 395 | print_vector(b.begin(), b.end()); 396 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 397 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 398 | a >= b); 399 | b.push_back(4.3); 400 | PRINT("vector a"); 401 | print_vector(a.begin(), a.end()); 402 | PRINT("vector b"); 403 | print_vector(b.begin(), b.end()); 404 | PRINT("a == b, a != b, a < b, a <= b, a > b, a >= b"); 405 | PRINT(a == b, ", ", a != b, ", ", a<b, ", ", a <= b, ", ", a> b, ", ", 406 | a >= b); 407 | } 408 | 409 | int main(int argc, char **argv) { 410 | std::cout << std::boolalpha; 411 | PRINT("constructor test"); 412 | vector_construct_test(); 413 | std::cout << "===== stl_method_test() =====\n"; 414 | stl_method_test(); 415 | performance_test(); 416 | erase_test(); 417 | insert_test(); 418 | swap_test(); 419 | compare_test(); 420 | 421 | // std::cout << std::distance(v.begin(), v.end()) << "\n"; 422 | (void)argc; 423 | std::string leak = std::string("leaks ") + &argv[0][2]; 424 | system(leak.c_str()); 425 | } 426 | --------------------------------------------------------------------------------