├── .gitattributes ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── License.txt ├── MSVC ├── MyTinySTL_VS2015.sln ├── MyTinySTL_VS2015.vcxproj └── MyTinySTL_VS2015.vcxproj.filters ├── MyTinySTL ├── algo.h ├── algobase.h ├── algorithm.h ├── alloc.h ├── allocator.h ├── astring.h ├── basic_string.h ├── construct.h ├── deque.h ├── exceptdef.h ├── functional.h ├── hashtable.h ├── heap_algo.h ├── iterator.h ├── list.h ├── map.h ├── memory.h ├── numeric.h ├── queue.h ├── rb_tree.h ├── set.h ├── set_algo.h ├── stack.h ├── stream_iterator.h ├── type_traits.h ├── uninitialized.h ├── unordered_map.h ├── unordered_set.h ├── util.h └── vector.h ├── README.md ├── Test ├── CMakeLists.txt ├── Lib │ └── redbud │ │ ├── io │ │ └── color.h │ │ └── platform.h ├── README.md ├── algorithm_performance_test.h ├── algorithm_test.h ├── deque_test.h ├── iterator_test.h ├── list_test.h ├── map_test.h ├── queue_test.h ├── set_test.h ├── stack_test.h ├── string_test.h ├── test.cpp ├── test.h ├── unordered_map_test.h ├── unordered_set_test.h └── vector_test.h └── appveyor.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Local build files 5 | *c.cmd 6 | *a.exe 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | [Xx]64/ 23 | [Xx]86/ 24 | [Bb]uild/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | 29 | # Visual Studio 2015 cache/options directory 30 | .vs/ 31 | 32 | # Visual Studio Code 33 | .vscode/ 34 | 35 | # Uncomment if you have tasks that create the project's static files in wwwroot 36 | #wwwroot/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # DNX 52 | project.lock.json 53 | artifacts/ 54 | 55 | *_i.c 56 | *_p.c 57 | *_i.h 58 | *.ilk 59 | *.meta 60 | *.obj 61 | *.pch 62 | *.pdb 63 | *.pgc 64 | *.pgd 65 | *.rsp 66 | *.sbr 67 | *.tlb 68 | *.tli 69 | *.tlh 70 | *.tmp 71 | *.tmp_proj 72 | *.log 73 | *.vspscc 74 | *.vssscc 75 | .builds 76 | *.pidb 77 | *.svclog 78 | *.scc 79 | 80 | # Chutzpah Test files 81 | _Chutzpah* 82 | 83 | # Visual C++ cache files 84 | ipch/ 85 | *.aps 86 | *.ncb 87 | *.opendb 88 | *.opensdf 89 | *.sdf 90 | *.cachefile 91 | *.VC.db 92 | 93 | # Visual Studio profiler 94 | *.psess 95 | *.vsp 96 | *.vspx 97 | *.sap 98 | 99 | # TFS 2012 Local Workspace 100 | $tf/ 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | *.DotSettings.user 109 | 110 | # JustCode is a .NET coding add-in 111 | .JustCode 112 | 113 | # TeamCity is a build add-in 114 | _TeamCity* 115 | 116 | # DotCover is a Code Coverage Tool 117 | *.dotCover 118 | 119 | # NCrunch 120 | _NCrunch_* 121 | .*crunch*.local.xml 122 | nCrunchTemp_* 123 | 124 | # MightyMoose 125 | *.mm.* 126 | AutoTest.Net/ 127 | 128 | # Web workbench (sass) 129 | .sass-cache/ 130 | 131 | # Installshield output folder 132 | [Ee]xpress/ 133 | 134 | # DocProject is a documentation generator add-in 135 | DocProject/buildhelp/ 136 | DocProject/Help/*.HxT 137 | DocProject/Help/*.HxC 138 | DocProject/Help/*.hhc 139 | DocProject/Help/*.hhk 140 | DocProject/Help/*.hhp 141 | DocProject/Help/Html2 142 | DocProject/Help/html 143 | 144 | # Click-Once directory 145 | publish/ 146 | 147 | # Publish Web Output 148 | *.[Pp]ublish.xml 149 | *.azurePubxml 150 | 151 | # TODO: Un-comment the next line if you do not want to checkin 152 | # your web deploy settings because they may include unencrypted 153 | # passwords 154 | #*.pubxml 155 | *.publishproj 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Microsoft Azure ApplicationInsights config file 178 | ApplicationInsights.config 179 | 180 | # Windows Store app package directory 181 | AppPackages/ 182 | BundleArtifacts/ 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | [Ss]tyle[Cc]op.* 193 | ~$* 194 | *~ 195 | *.dbmdl 196 | *.dbproj.schemaview 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # LightSwitch generated files 246 | GeneratedArtifacts/ 247 | ModelManifest.xml 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | # ubuntu 14.04 version 4 | sudo: required 5 | dist: trusty 6 | 7 | matrix: 8 | include: 9 | - os: linux 10 | compiler: gcc 11 | addons: 12 | apt: 13 | sources: ['ubuntu-toolchain-r-test'] 14 | packages: ['g++-5'] 15 | env: 16 | - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" 17 | 18 | - os: linux 19 | compiler: gcc 20 | addons: 21 | apt: 22 | sources: ['ubuntu-toolchain-r-test'] 23 | packages: ['g++-6'] 24 | env: 25 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 26 | 27 | - os: linux 28 | compiler: gcc 29 | addons: 30 | apt: 31 | sources: ['ubuntu-toolchain-r-test'] 32 | packages: ['g++-7'] 33 | env: 34 | - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" 35 | 36 | - os: osx 37 | osx_image: xcode5 38 | env: 39 | - MATRIX_EVAL="CC=clang && CXX=clang++" 40 | 41 | - os: osx 42 | osx_image: xcode6 43 | env: 44 | - MATRIX_EVAL="CC=clang && CXX=clang++" 45 | 46 | - os: osx 47 | osx_image: xcode7 48 | env: 49 | - MATRIX_EVAL="CC=clang && CXX=clang++" 50 | 51 | - os: osx 52 | osx_image: xcode8 53 | env: 54 | - MATRIX_EVAL="CC=clang && CXX=clang++" 55 | 56 | 57 | before_script: 58 | - eval "${MATRIX_EVAL}" 59 | - $CXX --version 60 | 61 | script: 62 | - mkdir build && cd ./build 63 | - cmake .. 64 | - make 65 | - cd ../bin && ./stltest 66 | 67 | branches: 68 | only: 69 | - master 70 | 71 | notifications: 72 | email: false 73 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(MyTinySTL) 4 | 5 | # version 6 | set(MyTinySTL_VERSION_MAJOR 2) 7 | set(MyTinySTL_VERSION_MINOR 0) 8 | set(MyTinySTL_VERSION_PATCH 0) 9 | set(MyTinySTL_VERSION "${MyTinySTL_VERSION_MAJOR}.${MyTinySTL_VERSION_MINOR}.${MyTinySTL_VERSION_PATCH}") 10 | message(STATUS "The version of this project is: ${MyTinySTL_VERSION}") 11 | 12 | # build type 13 | set(CMAKE_BUILD_TYPE release) 14 | 15 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -Wno-sign-compare -Wno-unused-but-set-variable -Wno-array-bounds") 17 | # set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion) 18 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0") 19 | message(FATAL_ERROR "required GCC 5.0 or later") 20 | else() 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 22 | endif() 23 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 24 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -Wno-sign-compare") 25 | # set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough) 26 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.5.0") 27 | message(FATAL_ERROR "required Clang 3.5 or later") 28 | else() 29 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 30 | endif() 31 | endif() 32 | 33 | message(STATUS "The cmake_cxx_flags is: ${CMAKE_CXX_FLAGS}") 34 | 35 | add_subdirectory(${PROJECT_SOURCE_DIR}/Test) 36 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Alinshans. All rights reserved. 2 | 3 | First published on github, see https://github.com/Alinshans/MyTinySTL 4 | 5 | The MyTinySTL source code is licensed under the MIT License. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /MSVC/MyTinySTL_VS2015.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyTinySTL", "MyTinySTL_VS2015.vcxproj", "{E88807F6-B07C-4371-BD38-FB1569F894E4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x64.ActiveCfg = Debug|x64 17 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x64.Build.0 = Debug|x64 18 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x86.ActiveCfg = Debug|Win32 19 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x86.Build.0 = Debug|Win32 20 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x64.ActiveCfg = Release|x64 21 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x64.Build.0 = Release|x64 22 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x86.ActiveCfg = Release|Win32 23 | {E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /MSVC/MyTinySTL_VS2015.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {E88807F6-B07C-4371-BD38-FB1569F894E4} 23 | Win32Proj 24 | MyTinySTL 25 | 8.1 26 | MyTinySTL 27 | 28 | 29 | 30 | Application 31 | true 32 | v140 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v140 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v140 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v140 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | 100 | 101 | 102 | 103 | Level4 104 | Disabled 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | 117 | 118 | MaxSpeed 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | Level4 134 | 135 | 136 | MaxSpeed 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /MSVC/MyTinySTL_VS2015.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 14 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 15 | 16 | 17 | {ec314ff3-dcde-4cac-a63a-4f6827750d0a} 18 | 19 | 20 | {c6f24d77-e6f0-439e-954a-c0ca577689d5} 21 | 22 | 23 | 24 | 25 | include 26 | 27 | 28 | include 29 | 30 | 31 | include 32 | 33 | 34 | include 35 | 36 | 37 | include 38 | 39 | 40 | include 41 | 42 | 43 | include 44 | 45 | 46 | include 47 | 48 | 49 | include 50 | 51 | 52 | include 53 | 54 | 55 | include 56 | 57 | 58 | include 59 | 60 | 61 | include 62 | 63 | 64 | include 65 | 66 | 67 | include 68 | 69 | 70 | include 71 | 72 | 73 | include 74 | 75 | 76 | include 77 | 78 | 79 | include 80 | 81 | 82 | include 83 | 84 | 85 | include 86 | 87 | 88 | include 89 | 90 | 91 | include 92 | 93 | 94 | include 95 | 96 | 97 | include 98 | 99 | 100 | include 101 | 102 | 103 | test 104 | 105 | 106 | test 107 | 108 | 109 | test 110 | 111 | 112 | test 113 | 114 | 115 | test 116 | 117 | 118 | test 119 | 120 | 121 | test 122 | 123 | 124 | test 125 | 126 | 127 | test 128 | 129 | 130 | test 131 | 132 | 133 | test 134 | 135 | 136 | test 137 | 138 | 139 | test 140 | 141 | 142 | test\Lib 143 | 144 | 145 | test\Lib 146 | 147 | 148 | include 149 | 150 | 151 | include 152 | 153 | 154 | include 155 | 156 | 157 | 158 | 159 | test 160 | 161 | 162 | -------------------------------------------------------------------------------- /MyTinySTL/algorithm.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ALGORITHM_H_ 2 | #define MYTINYSTL_ALGORITHM_H_ 3 | 4 | // 这个头文件包含了 mystl 的所有算法,包括基本算法,数值算法,heap 算法,set 算法和其他算法 5 | 6 | #include "algobase.h" 7 | #include "algo.h" 8 | #include "set_algo.h" 9 | #include "heap_algo.h" 10 | #include "numeric.h" 11 | 12 | namespace mystl 13 | { 14 | 15 | } // namespace mystl 16 | 17 | #endif // !MYTINYSTL_ALGORITHM_H_ 18 | 19 | -------------------------------------------------------------------------------- /MyTinySTL/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ALLOC_H_ 2 | #define MYTINYSTL_ALLOC_H_ 3 | 4 | // 这个头文件包含一个类 alloc,用于分配和回收内存,以内存池的方式实现 5 | // 6 | // 从 v2.0.0 版本开始,将不再使用内存池,这个文件将被弃用,但暂时保留 7 | // 8 | // 注意!!! 9 | // 我知道这个文件里很多实现是错的,这是很久很久前写的了,后面已经不用这个东西了, 10 | // 所以我也没再维护,有诸多问题,已经有人在issue中都提了,free_list的修改, 11 | // 指针作为参数时没实际修改到原指针,等等。相信会看这么仔细的,大部分都是 12 | // 初学C++的朋友,大佬都不会看这些玩具了,所以其中的错误,就留给对内存池实现 13 | // 感兴趣的朋友去修改啦! 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | namespace mystl 21 | { 22 | 23 | // 共用体: FreeList 24 | // 采用链表的方式管理内存碎片,分配与回收小内存(<=4K)区块 25 | union FreeList 26 | { 27 | union FreeList* next; // 指向下一个区块 28 | char data[1]; // 储存本块内存的首地址 29 | }; 30 | 31 | // 不同内存范围的上调大小 32 | enum 33 | { 34 | EAlign128 = 8, 35 | EAlign256 = 16, 36 | EAlign512 = 32, 37 | EAlign1024 = 64, 38 | EAlign2048 = 128, 39 | EAlign4096 = 256 40 | }; 41 | 42 | // 小对象的内存大小 43 | enum { ESmallObjectBytes = 4096 }; 44 | 45 | // free lists 个数 46 | enum { EFreeListsNumber = 56 }; 47 | 48 | // 空间配置类 alloc 49 | // 如果内存较大,超过 4096 bytes,直接调用 std::malloc, std::free 50 | // 当内存较小时,以内存池管理,每次配置一大块内存,并维护对应的自由链表 51 | class alloc 52 | { 53 | private: 54 | static char* start_free; // 内存池起始位置 55 | static char* end_free; // 内存池结束位置 56 | static size_t heap_size; // 申请 heap 空间附加值大小 57 | 58 | static FreeList* free_list[EFreeListsNumber]; // 自由链表 59 | 60 | public: 61 | static void* allocate(size_t n); 62 | static void deallocate(void* p, size_t n); 63 | static void* reallocate(void* p, size_t old_size, size_t new_size); 64 | 65 | private: 66 | static size_t M_align(size_t bytes); 67 | static size_t M_round_up(size_t bytes); 68 | static size_t M_freelist_index(size_t bytes); 69 | static void* M_refill(size_t n); 70 | static char* M_chunk_alloc(size_t size, size_t &nobj); 71 | }; 72 | 73 | // 静态成员变量初始化 74 | 75 | char* alloc::start_free = nullptr; 76 | char* alloc::end_free = nullptr; 77 | size_t alloc::heap_size = 0; 78 | 79 | FreeList* alloc::free_list[EFreeListsNumber] = { 80 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 81 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 82 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 83 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 84 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 85 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, 86 | nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr 87 | }; 88 | 89 | // 分配大小为 n 的空间, n > 0 90 | inline void* alloc::allocate(size_t n) 91 | { 92 | FreeList* my_free_list; 93 | FreeList* result; 94 | if (n > static_cast(ESmallObjectBytes)) 95 | return std::malloc(n); 96 | my_free_list = free_list[M_freelist_index(n)]; 97 | result = my_free_list; 98 | if (result == nullptr) 99 | { 100 | void* r = M_refill(M_round_up(n)); 101 | return r; 102 | } 103 | my_free_list = result->next; 104 | return result; 105 | } 106 | 107 | // 释放 p 指向的大小为 n 的空间, p 不能为 0 108 | inline void alloc::deallocate(void* p, size_t n) 109 | { 110 | if (n > static_cast(ESmallObjectBytes)) 111 | { 112 | std::free(p); 113 | return; 114 | } 115 | FreeList* q = reinterpret_cast(p); 116 | FreeList* my_free_list; 117 | my_free_list = free_list[M_freelist_index(n)]; 118 | q->next = my_free_list; 119 | my_free_list = q; 120 | } 121 | 122 | // 重新分配空间,接受三个参数,参数一为指向新空间的指针,参数二为原来空间的大小,参数三为申请空间的大小 123 | inline void* alloc::reallocate(void* p, size_t old_size, size_t new_size) 124 | { 125 | deallocate(p, old_size); 126 | p = allocate(new_size); 127 | return p; 128 | } 129 | 130 | // bytes 对应上调大小 131 | inline size_t alloc::M_align(size_t bytes) 132 | { 133 | if (bytes <= 512) 134 | { 135 | return bytes <= 256 136 | ? bytes <= 128 ? EAlign128 : EAlign256 137 | : EAlign512; 138 | } 139 | return bytes <= 2048 140 | ? bytes <= 1024 ? EAlign1024 : EAlign2048 141 | : EAlign4096; 142 | } 143 | 144 | // 将 bytes 上调至对应区间大小 145 | inline size_t alloc::M_round_up(size_t bytes) 146 | { 147 | return ((bytes + M_align(bytes) - 1) & ~(M_align(bytes) - 1)); 148 | } 149 | 150 | // 根据区块大小,选择第 n 个 free lists 151 | inline size_t alloc::M_freelist_index(size_t bytes) 152 | { 153 | if (bytes <= 512) 154 | { 155 | return bytes <= 256 156 | ? bytes <= 128 157 | ? ((bytes + EAlign128 - 1) / EAlign128 - 1) 158 | : (15 + (bytes + EAlign256 - 129) / EAlign256) 159 | : (23 + (bytes + EAlign512 - 257) / EAlign512); 160 | } 161 | return bytes <= 2048 162 | ? bytes <= 1024 163 | ? (31 + (bytes + EAlign1024 - 513) / EAlign1024) 164 | : (39 + (bytes + EAlign2048 - 1025) / EAlign2048) 165 | : (47 + (bytes + EAlign4096 - 2049) / EAlign4096); 166 | } 167 | 168 | // 重新填充 free list 169 | void* alloc::M_refill(size_t n) 170 | { 171 | size_t nblock = 10; 172 | char* c = M_chunk_alloc(n, nblock); 173 | FreeList* my_free_list; 174 | FreeList* result, *cur, *next; 175 | // 如果只有一个区块,就把这个区块返回给调用者,free list 没有增加新节点 176 | if (nblock == 1) 177 | return c; 178 | // 否则把一个区块给调用者,剩下的纳入 free list 作为新节点 179 | my_free_list = free_list[M_freelist_index(n)]; 180 | result = (FreeList*)c; 181 | my_free_list = next = (FreeList*)(c + n); 182 | for (size_t i = 1; ; ++i) 183 | { 184 | cur = next; 185 | next = (FreeList*)((char*)next + n); 186 | if (nblock - 1 == i) 187 | { 188 | cur->next = nullptr; 189 | break; 190 | } 191 | else 192 | { 193 | cur->next = next; 194 | } 195 | } 196 | return result; 197 | } 198 | 199 | // 从内存池中取空间给 free list 使用,条件不允许时,会调整 nblock 200 | char* alloc::M_chunk_alloc(size_t size, size_t& nblock) 201 | { 202 | char* result; 203 | size_t need_bytes = size * nblock; 204 | size_t pool_bytes = end_free - start_free; 205 | 206 | // 如果内存池剩余大小完全满足需求量,返回它 207 | if (pool_bytes >= need_bytes) 208 | { 209 | result = start_free; 210 | start_free += need_bytes; 211 | return result; 212 | } 213 | 214 | // 如果内存池剩余大小不能完全满足需求量,但至少可以分配一个或一个以上的区块,就返回它 215 | else if (pool_bytes >= size) 216 | { 217 | nblock = pool_bytes / size; 218 | need_bytes = size * nblock; 219 | result = start_free; 220 | start_free += need_bytes; 221 | return result; 222 | } 223 | 224 | // 如果内存池剩余大小连一个区块都无法满足 225 | else 226 | { 227 | if (pool_bytes > 0) 228 | { // 如果内存池还有剩余,把剩余的空间加入到 free list 中 229 | FreeList* my_free_list = free_list[M_freelist_index(pool_bytes)]; 230 | ((FreeList*)start_free)->next = my_free_list; 231 | my_free_list = (FreeList*)start_free; 232 | } 233 | // 申请 heap 空间 234 | size_t bytes_to_get = (need_bytes << 1) + M_round_up(heap_size >> 4); 235 | start_free = (char*)std::malloc(bytes_to_get); 236 | if (!start_free) 237 | { // heap 空间也不够 238 | FreeList* my_free_list, *p; 239 | // 试着查找有无未用区块,且区块足够大的 free list 240 | for (size_t i = size; i <= ESmallObjectBytes; i += M_align(i)) 241 | { 242 | my_free_list = free_list[M_freelist_index(i)]; 243 | p = my_free_list; 244 | if (p) 245 | { 246 | my_free_list = p->next; 247 | start_free = (char*)p; 248 | end_free = start_free + i; 249 | return M_chunk_alloc(size, nblock); 250 | } 251 | } 252 | std::printf("out of memory"); 253 | end_free = nullptr; 254 | throw std::bad_alloc(); 255 | } 256 | end_free = start_free + bytes_to_get; 257 | heap_size += bytes_to_get; 258 | return M_chunk_alloc(size, nblock); 259 | } 260 | } 261 | 262 | } // namespace mystl 263 | #endif // !MYTINYSTL_ALLOC_H_ 264 | 265 | -------------------------------------------------------------------------------- /MyTinySTL/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ALLOCATOR_H_ 2 | #define MYTINYSTL_ALLOCATOR_H_ 3 | 4 | // 这个头文件包含一个模板类 allocator,用于管理内存的分配、释放,对象的构造、析构 5 | 6 | #include "construct.h" 7 | #include "util.h" 8 | 9 | namespace mystl 10 | { 11 | 12 | // 模板类:allocator 13 | // 模板函数代表数据类型 14 | template 15 | class allocator 16 | { 17 | public: 18 | typedef T value_type; 19 | typedef T* pointer; 20 | typedef const T* const_pointer; 21 | typedef T& reference; 22 | typedef const T& const_reference; 23 | typedef size_t size_type; 24 | typedef ptrdiff_t difference_type; 25 | 26 | public: 27 | static T* allocate(); 28 | static T* allocate(size_type n); 29 | 30 | static void deallocate(T* ptr); 31 | static void deallocate(T* ptr, size_type n); 32 | 33 | static void construct(T* ptr); 34 | static void construct(T* ptr, const T& value); 35 | static void construct(T* ptr, T&& value); 36 | 37 | template 38 | static void construct(T* ptr, Args&& ...args); 39 | 40 | static void destroy(T* ptr); 41 | static void destroy(T* first, T* last); 42 | }; 43 | 44 | template 45 | T* allocator::allocate() 46 | { 47 | return static_cast(::operator new(sizeof(T))); 48 | } 49 | 50 | template 51 | T* allocator::allocate(size_type n) 52 | { 53 | if (n == 0) 54 | return nullptr; 55 | return static_cast(::operator new(n * sizeof(T))); 56 | } 57 | 58 | template 59 | void allocator::deallocate(T* ptr) 60 | { 61 | if (ptr == nullptr) 62 | return; 63 | ::operator delete(ptr); 64 | } 65 | 66 | template 67 | void allocator::deallocate(T* ptr, size_type /*size*/) 68 | { 69 | if (ptr == nullptr) 70 | return; 71 | ::operator delete(ptr); 72 | } 73 | 74 | template 75 | void allocator::construct(T* ptr) 76 | { 77 | mystl::construct(ptr); 78 | } 79 | 80 | template 81 | void allocator::construct(T* ptr, const T& value) 82 | { 83 | mystl::construct(ptr, value); 84 | } 85 | 86 | template 87 | void allocator::construct(T* ptr, T&& value) 88 | { 89 | mystl::construct(ptr, mystl::move(value)); 90 | } 91 | 92 | template 93 | template 94 | void allocator::construct(T* ptr, Args&& ...args) 95 | { 96 | mystl::construct(ptr, mystl::forward(args)...); 97 | } 98 | 99 | template 100 | void allocator::destroy(T* ptr) 101 | { 102 | mystl::destroy(ptr); 103 | } 104 | 105 | template 106 | void allocator::destroy(T* first, T* last) 107 | { 108 | mystl::destroy(first, last); 109 | } 110 | 111 | } // namespace mystl 112 | #endif // !MYTINYSTL_ALLOCATOR_H_ 113 | 114 | -------------------------------------------------------------------------------- /MyTinySTL/astring.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ASTRING_H_ 2 | #define MYTINYSTL_ASTRING_H_ 3 | 4 | // 定义了 string, wstring, u16string, u32string 类型 5 | 6 | #include "basic_string.h" 7 | 8 | namespace mystl 9 | { 10 | 11 | using string = mystl::basic_string; 12 | using wstring = mystl::basic_string; 13 | using u16string = mystl::basic_string; 14 | using u32string = mystl::basic_string; 15 | 16 | } 17 | #endif // !MYTINYSTL_ASTRING_H_ 18 | 19 | -------------------------------------------------------------------------------- /MyTinySTL/construct.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_CONSTRUCT_H_ 2 | #define MYTINYSTL_CONSTRUCT_H_ 3 | 4 | // 这个头文件包含两个函数 construct,destroy 5 | // construct : 负责对象的构造 6 | // destroy : 负责对象的析构 7 | 8 | #include 9 | 10 | #include "type_traits.h" 11 | #include "iterator.h" 12 | 13 | #ifdef _MSC_VER 14 | #pragma warning(push) 15 | #pragma warning(disable : 4100) // unused parameter 16 | #endif // _MSC_VER 17 | 18 | namespace mystl 19 | { 20 | 21 | // construct 构造对象 22 | 23 | template 24 | void construct(Ty* ptr) 25 | { 26 | ::new ((void*)ptr) Ty(); 27 | } 28 | 29 | template 30 | void construct(Ty1* ptr, const Ty2& value) 31 | { 32 | ::new ((void*)ptr) Ty1(value); 33 | } 34 | 35 | template 36 | void construct(Ty* ptr, Args&&... args) 37 | { 38 | ::new ((void*)ptr) Ty(mystl::forward(args)...); 39 | } 40 | 41 | // destroy 将对象析构 42 | 43 | template 44 | void destroy_one(Ty*, std::true_type) {} 45 | 46 | template 47 | void destroy_one(Ty* pointer, std::false_type) 48 | { 49 | if (pointer != nullptr) 50 | { 51 | pointer->~Ty(); 52 | } 53 | } 54 | 55 | template 56 | void destroy_cat(ForwardIter , ForwardIter , std::true_type) {} 57 | 58 | template 59 | void destroy_cat(ForwardIter first, ForwardIter last, std::false_type) 60 | { 61 | for (; first != last; ++first) 62 | destroy(&*first); 63 | } 64 | 65 | template 66 | void destroy(Ty* pointer) 67 | { 68 | destroy_one(pointer, std::is_trivially_destructible{}); 69 | } 70 | 71 | template 72 | void destroy(ForwardIter first, ForwardIter last) 73 | { 74 | destroy_cat(first, last, std::is_trivially_destructible< 75 | typename iterator_traits::value_type>{}); 76 | } 77 | 78 | } // namespace mystl 79 | 80 | #ifdef _MSC_VER 81 | #pragma warning(pop) 82 | #endif // _MSC_VER 83 | 84 | #endif // !MYTINYSTL_CONSTRUCT_H_ 85 | 86 | -------------------------------------------------------------------------------- /MyTinySTL/exceptdef.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_EXCEPTDEF_H_ 2 | #define MYTINYSTL_EXCEPTDEF_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace mystl 9 | { 10 | 11 | #define MYSTL_DEBUG(expr) \ 12 | assert(expr) 13 | 14 | #define THROW_LENGTH_ERROR_IF(expr, what) \ 15 | if ((expr)) throw std::length_error(what) 16 | 17 | #define THROW_OUT_OF_RANGE_IF(expr, what) \ 18 | if ((expr)) throw std::out_of_range(what) 19 | 20 | #define THROW_RUNTIME_ERROR_IF(expr, what) \ 21 | if ((expr)) throw std::runtime_error(what) 22 | 23 | } // namepsace mystl 24 | 25 | #endif // !MYTINYSTL_EXCEPTDEF_H_ 26 | 27 | -------------------------------------------------------------------------------- /MyTinySTL/functional.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_FUNCTIONAL_H_ 2 | #define MYTINYSTL_FUNCTIONAL_H_ 3 | 4 | // 这个头文件包含了 mystl 的函数对象与哈希函数 5 | 6 | #include 7 | 8 | namespace mystl 9 | { 10 | 11 | // 定义一元函数的参数型别和返回值型别 12 | template 13 | struct unarg_function 14 | { 15 | typedef Arg argument_type; 16 | typedef Result result_type; 17 | }; 18 | 19 | // 定义二元函数的参数型别的返回值型别 20 | template 21 | struct binary_function 22 | { 23 | typedef Arg1 first_argument_type; 24 | typedef Arg2 second_argument_type; 25 | typedef Result result_type; 26 | }; 27 | 28 | // 函数对象:加法 29 | template 30 | struct plus :public binary_function 31 | { 32 | T operator()(const T& x, const T& y) const { return x + y; } 33 | }; 34 | 35 | // 函数对象:减法 36 | template 37 | struct minus :public binary_function 38 | { 39 | T operator()(const T& x, const T& y) const { return x - y; } 40 | }; 41 | 42 | // 函数对象:乘法 43 | template 44 | struct multiplies :public binary_function 45 | { 46 | T operator()(const T& x, const T& y) const { return x * y; } 47 | }; 48 | 49 | // 函数对象:除法 50 | template 51 | struct divides :public binary_function 52 | { 53 | T operator()(const T& x, const T& y) const { return x / y; } 54 | }; 55 | 56 | // 函数对象:模取 57 | template 58 | struct modulus :public binary_function 59 | { 60 | T operator()(const T& x, const T& y) const { return x % y; } 61 | }; 62 | 63 | // 函数对象:否定 64 | template 65 | struct negate :public unarg_function 66 | { 67 | T operator()(const T& x) const { return -x; } 68 | }; 69 | 70 | // 加法的证同元素 71 | template 72 | T identity_element(plus) { return T(0); } 73 | 74 | // 乘法的证同元素 75 | template 76 | T identity_element(multiplies) { return T(1); } 77 | 78 | // 函数对象:等于 79 | template 80 | struct equal_to :public binary_function 81 | { 82 | bool operator()(const T& x, const T& y) const { return x == y; } 83 | }; 84 | 85 | // 函数对象:不等于 86 | template 87 | struct not_equal_to :public binary_function 88 | { 89 | bool operator()(const T& x, const T& y) const { return x != y; } 90 | }; 91 | 92 | // 函数对象:大于 93 | template 94 | struct greater :public binary_function 95 | { 96 | bool operator()(const T& x, const T& y) const { return x > y; } 97 | }; 98 | 99 | // 函数对象:小于 100 | template 101 | struct less :public binary_function 102 | { 103 | bool operator()(const T& x, const T& y) const { return x < y; } 104 | }; 105 | 106 | // 函数对象:大于等于 107 | template 108 | struct greater_equal :public binary_function 109 | { 110 | bool operator()(const T& x, const T& y) const { return x >= y; } 111 | }; 112 | 113 | // 函数对象:小于等于 114 | template 115 | struct less_equal :public binary_function 116 | { 117 | bool operator()(const T& x, const T& y) const { return x <= y; } 118 | }; 119 | 120 | // 函数对象:逻辑与 121 | template 122 | struct logical_and :public binary_function 123 | { 124 | bool operator()(const T& x, const T& y) const { return x && y; } 125 | }; 126 | 127 | // 函数对象:逻辑或 128 | template 129 | struct logical_or :public binary_function 130 | { 131 | bool operator()(const T& x, const T& y) const { return x || y; } 132 | }; 133 | 134 | // 函数对象:逻辑非 135 | template 136 | struct logical_not :public unarg_function 137 | { 138 | bool operator()(const T& x) const { return !x; } 139 | }; 140 | 141 | // 证同函数:不会改变元素,返回本身 142 | template 143 | struct identity :public unarg_function 144 | { 145 | const T& operator()(const T& x) const { return x; } 146 | }; 147 | 148 | // 选择函数:接受一个 pair,返回第一个元素 149 | template 150 | struct selectfirst :public unarg_function 151 | { 152 | const typename Pair::first_type& operator()(const Pair& x) const 153 | { 154 | return x.first; 155 | } 156 | }; 157 | 158 | // 选择函数:接受一个 pair,返回第二个元素 159 | template 160 | struct selectsecond :public unarg_function 161 | { 162 | const typename Pair::second_type& operator()(const Pair& x) const 163 | { 164 | return x.second; 165 | } 166 | }; 167 | 168 | // 投射函数:返回第一参数 169 | template 170 | struct projectfirst :public binary_function 171 | { 172 | Arg1 operator()(const Arg1& x, const Arg2&) const { return x; } 173 | }; 174 | 175 | // 投射函数:返回第二参数 176 | template 177 | struct projectsecond :public binary_function 178 | { 179 | Arg2 operator()(const Arg1&, const Arg2& y) const { return y; } 180 | }; 181 | 182 | /*****************************************************************************************/ 183 | // 哈希函数对象 184 | 185 | // 对于大部分类型,hash function 什么都不做 186 | template 187 | struct hash {}; 188 | 189 | // 针对指针的偏特化版本 190 | template 191 | struct hash 192 | { 193 | size_t operator()(T* p) const noexcept 194 | { return reinterpret_cast(p); } 195 | }; 196 | 197 | // 对于整型类型,只是返回原值 198 | #define MYSTL_TRIVIAL_HASH_FCN(Type) \ 199 | template <> struct hash \ 200 | { \ 201 | size_t operator()(Type val) const noexcept \ 202 | { return static_cast(val); } \ 203 | }; 204 | 205 | MYSTL_TRIVIAL_HASH_FCN(bool) 206 | 207 | MYSTL_TRIVIAL_HASH_FCN(char) 208 | 209 | MYSTL_TRIVIAL_HASH_FCN(signed char) 210 | 211 | MYSTL_TRIVIAL_HASH_FCN(unsigned char) 212 | 213 | MYSTL_TRIVIAL_HASH_FCN(wchar_t) 214 | 215 | MYSTL_TRIVIAL_HASH_FCN(char16_t) 216 | 217 | MYSTL_TRIVIAL_HASH_FCN(char32_t) 218 | 219 | MYSTL_TRIVIAL_HASH_FCN(short) 220 | 221 | MYSTL_TRIVIAL_HASH_FCN(unsigned short) 222 | 223 | MYSTL_TRIVIAL_HASH_FCN(int) 224 | 225 | MYSTL_TRIVIAL_HASH_FCN(unsigned int) 226 | 227 | MYSTL_TRIVIAL_HASH_FCN(long) 228 | 229 | MYSTL_TRIVIAL_HASH_FCN(unsigned long) 230 | 231 | MYSTL_TRIVIAL_HASH_FCN(long long) 232 | 233 | MYSTL_TRIVIAL_HASH_FCN(unsigned long long) 234 | 235 | #undef MYSTL_TRIVIAL_HASH_FCN 236 | 237 | // 对于浮点数,逐位哈希 238 | inline size_t bitwise_hash(const unsigned char* first, size_t count) 239 | { 240 | #if (_MSC_VER && _WIN64) || ((__GNUC__ || __clang__) &&__SIZEOF_POINTER__ == 8) 241 | const size_t fnv_offset = 14695981039346656037ull; 242 | const size_t fnv_prime = 1099511628211ull; 243 | #else 244 | const size_t fnv_offset = 2166136261u; 245 | const size_t fnv_prime = 16777619u; 246 | #endif 247 | size_t result = fnv_offset; 248 | for (size_t i = 0; i < count; ++i) 249 | { 250 | result ^= (size_t)first[i]; 251 | result *= fnv_prime; 252 | } 253 | return result; 254 | } 255 | 256 | template <> 257 | struct hash 258 | { 259 | size_t operator()(const float& val) 260 | { 261 | return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(float)); 262 | } 263 | }; 264 | 265 | template <> 266 | struct hash 267 | { 268 | size_t operator()(const double& val) 269 | { 270 | return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(double)); 271 | } 272 | }; 273 | 274 | template <> 275 | struct hash 276 | { 277 | size_t operator()(const long double& val) 278 | { 279 | return val == 0.0f ? 0 : bitwise_hash((const unsigned char*)&val, sizeof(long double)); 280 | } 281 | }; 282 | 283 | } // namespace mystl 284 | #endif // !MYTINYSTL_FUNCTIONAL_H_ 285 | 286 | -------------------------------------------------------------------------------- /MyTinySTL/heap_algo.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_HEAP_ALGO_H_ 2 | #define MYTINYSTL_HEAP_ALGO_H_ 3 | 4 | // 这个头文件包含 heap 的四个算法 : push_heap, pop_heap, sort_heap, make_heap 5 | 6 | #include "iterator.h" 7 | 8 | namespace mystl 9 | { 10 | 11 | /*****************************************************************************************/ 12 | // push_heap 13 | // 该函数接受两个迭代器,表示一个 heap 容器的首尾,并且新元素已经插入到底部容器的最尾端,调整 heap 14 | /*****************************************************************************************/ 15 | template 16 | void push_heap_aux(RandomIter first, Distance holeIndex, Distance topIndex, T value) 17 | { 18 | auto parent = (holeIndex - 1) / 2; 19 | while (holeIndex > topIndex && *(first + parent) < value) 20 | { 21 | // 使用 operator<,所以 heap 为 max-heap 22 | *(first + holeIndex) = *(first + parent); 23 | holeIndex = parent; 24 | parent = (holeIndex - 1) / 2; 25 | } 26 | *(first + holeIndex) = value; 27 | } 28 | 29 | template 30 | void push_heap_d(RandomIter first, RandomIter last, Distance*) 31 | { 32 | mystl::push_heap_aux(first, (last - first) - 1, static_cast(0), *(last - 1)); 33 | } 34 | 35 | template 36 | void push_heap(RandomIter first, RandomIter last) 37 | { // 新元素应该已置于底部容器的最尾端 38 | mystl::push_heap_d(first, last, distance_type(first)); 39 | } 40 | 41 | // 重载版本使用函数对象 comp 代替比较操作 42 | template 43 | void push_heap_aux(RandomIter first, Distance holeIndex, Distance topIndex, T value, 44 | Compared comp) 45 | { 46 | auto parent = (holeIndex - 1) / 2; 47 | while (holeIndex > topIndex && comp(*(first + parent), value)) 48 | { 49 | *(first + holeIndex) = *(first + parent); 50 | holeIndex = parent; 51 | parent = (holeIndex - 1) / 2; 52 | } 53 | *(first + holeIndex) = value; 54 | } 55 | 56 | template 57 | void push_heap_d(RandomIter first, RandomIter last, Distance*, Compared comp) 58 | { 59 | mystl::push_heap_aux(first, (last - first) - 1, static_cast(0), 60 | *(last - 1), comp); 61 | } 62 | 63 | template 64 | void push_heap(RandomIter first, RandomIter last, Compared comp) 65 | { 66 | mystl::push_heap_d(first, last, distance_type(first), comp); 67 | } 68 | 69 | /*****************************************************************************************/ 70 | // pop_heap 71 | // 该函数接受两个迭代器,表示 heap 容器的首尾,将 heap 的根节点取出放到容器尾部,调整 heap 72 | /*****************************************************************************************/ 73 | template 74 | void adjust_heap(RandomIter first, Distance holeIndex, Distance len, T value) 75 | { 76 | // 先进行下溯(percolate down)过程 77 | auto topIndex = holeIndex; 78 | auto rchild = 2 * holeIndex + 2; 79 | while (rchild < len) 80 | { 81 | if (*(first + rchild) < *(first + rchild - 1)) 82 | --rchild; 83 | *(first + holeIndex) = *(first + rchild); 84 | holeIndex = rchild; 85 | rchild = 2 * (rchild + 1); 86 | } 87 | if (rchild == len) 88 | { // 如果没有右子节点 89 | *(first + holeIndex) = *(first + (rchild - 1)); 90 | holeIndex = rchild - 1; 91 | } 92 | // 再执行一次上溯(percolate up)过程 93 | mystl::push_heap_aux(first, holeIndex, topIndex, value); 94 | } 95 | 96 | template 97 | void pop_heap_aux(RandomIter first, RandomIter last, RandomIter result, T value, 98 | Distance*) 99 | { 100 | // 先将首值调至尾节点,然后调整[first, last - 1)使之重新成为一个 max-heap 101 | *result = *first; 102 | mystl::adjust_heap(first, static_cast(0), last - first, value); 103 | } 104 | 105 | template 106 | void pop_heap(RandomIter first, RandomIter last) 107 | { 108 | mystl::pop_heap_aux(first, last - 1, last - 1, *(last - 1), distance_type(first)); 109 | } 110 | 111 | // 重载版本使用函数对象 comp 代替比较操作 112 | template 113 | void adjust_heap(RandomIter first, Distance holeIndex, Distance len, T value, 114 | Compared comp) 115 | { 116 | // 先进行下溯(percolate down)过程 117 | auto topIndex = holeIndex; 118 | auto rchild = 2 * holeIndex + 2; 119 | while (rchild < len) 120 | { 121 | if (comp(*(first + rchild), *(first + rchild - 1))) --rchild; 122 | *(first + holeIndex) = *(first + rchild); 123 | holeIndex = rchild; 124 | rchild = 2 * (rchild + 1); 125 | } 126 | if (rchild == len) 127 | { 128 | *(first + holeIndex) = *(first + (rchild - 1)); 129 | holeIndex = rchild - 1; 130 | } 131 | // 再执行一次上溯(percolate up)过程 132 | mystl::push_heap_aux(first, holeIndex, topIndex, value, comp); 133 | } 134 | 135 | template 136 | void pop_heap_aux(RandomIter first, RandomIter last, RandomIter result, 137 | T value, Distance*, Compared comp) 138 | { 139 | *result = *first; // 先将尾指设置成首值,即尾指为欲求结果 140 | mystl::adjust_heap(first, static_cast(0), last - first, value, comp); 141 | } 142 | 143 | template 144 | void pop_heap(RandomIter first, RandomIter last, Compared comp) 145 | { 146 | mystl::pop_heap_aux(first, last - 1, last - 1, *(last - 1), 147 | distance_type(first), comp); 148 | } 149 | 150 | /*****************************************************************************************/ 151 | // sort_heap 152 | // 该函数接受两个迭代器,表示 heap 容器的首尾,不断执行 pop_heap 操作,直到首尾最多相差1 153 | /*****************************************************************************************/ 154 | template 155 | void sort_heap(RandomIter first, RandomIter last) 156 | { 157 | // 每执行一次 pop_heap,最大的元素都被放到尾部,直到容器最多只有一个元素,完成排序 158 | while (last - first > 1) 159 | { 160 | mystl::pop_heap(first, last--); 161 | } 162 | } 163 | 164 | // 重载版本使用函数对象 comp 代替比较操作 165 | template 166 | void sort_heap(RandomIter first, RandomIter last, Compared comp) 167 | { 168 | while (last - first > 1) 169 | { 170 | mystl::pop_heap(first, last--, comp); 171 | } 172 | } 173 | 174 | /*****************************************************************************************/ 175 | // make_heap 176 | // 该函数接受两个迭代器,表示 heap 容器的首尾,把容器内的数据变为一个 heap 177 | /*****************************************************************************************/ 178 | template 179 | void make_heap_aux(RandomIter first, RandomIter last, Distance*) 180 | { 181 | if (last - first < 2) 182 | return; 183 | auto len = last - first; 184 | auto holeIndex = (len - 2) / 2; 185 | while (true) 186 | { 187 | // 重排以 holeIndex 为首的子树 188 | mystl::adjust_heap(first, holeIndex, len, *(first + holeIndex)); 189 | if (holeIndex == 0) 190 | return; 191 | holeIndex--; 192 | } 193 | } 194 | 195 | template 196 | void make_heap(RandomIter first, RandomIter last) 197 | { 198 | mystl::make_heap_aux(first, last, distance_type(first));; 199 | } 200 | 201 | // 重载版本使用函数对象 comp 代替比较操作 202 | template 203 | void make_heap_aux(RandomIter first, RandomIter last, Distance*, Compared comp) 204 | { 205 | if (last - first < 2) 206 | return; 207 | auto len = last - first; 208 | auto holeIndex = (len - 2) / 2; 209 | while (true) 210 | { 211 | // 重排以 holeIndex 为首的子树 212 | mystl::adjust_heap(first, holeIndex, len, *(first + holeIndex), comp); 213 | if (holeIndex == 0) 214 | return; 215 | holeIndex--; 216 | } 217 | } 218 | 219 | template 220 | void make_heap(RandomIter first, RandomIter last, Compared comp) 221 | { 222 | mystl::make_heap_aux(first, last, distance_type(first), comp); 223 | } 224 | 225 | } // namespace mystl 226 | #endif // !MYTINYSTL_HEAP_ALGO_H_ 227 | 228 | -------------------------------------------------------------------------------- /MyTinySTL/iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ITERATOR_H_ 2 | #define MYTINYSTL_ITERATOR_H_ 3 | 4 | // 这个头文件用于迭代器设计,包含了一些模板结构体与全局函数, 5 | 6 | #include 7 | 8 | #include "type_traits.h" 9 | 10 | namespace mystl 11 | { 12 | 13 | // 五种迭代器类型 14 | struct input_iterator_tag {}; 15 | struct output_iterator_tag {}; 16 | struct forward_iterator_tag : public input_iterator_tag {}; 17 | struct bidirectional_iterator_tag : public forward_iterator_tag {}; 18 | struct random_access_iterator_tag : public bidirectional_iterator_tag {}; 19 | 20 | // iterator 模板 21 | template 23 | struct iterator 24 | { 25 | typedef Category iterator_category; 26 | typedef T value_type; 27 | typedef Pointer pointer; 28 | typedef Reference reference; 29 | typedef Distance difference_type; 30 | }; 31 | 32 | // iterator traits 33 | 34 | template 35 | struct has_iterator_cat 36 | { 37 | private: 38 | struct two { char a; char b; }; 39 | template static two test(...); 40 | template static char test(typename U::iterator_category* = 0); 41 | public: 42 | static const bool value = sizeof(test(0)) == sizeof(char); 43 | }; 44 | 45 | template 46 | struct iterator_traits_impl {}; 47 | 48 | template 49 | struct iterator_traits_impl 50 | { 51 | typedef typename Iterator::iterator_category iterator_category; 52 | typedef typename Iterator::value_type value_type; 53 | typedef typename Iterator::pointer pointer; 54 | typedef typename Iterator::reference reference; 55 | typedef typename Iterator::difference_type difference_type; 56 | }; 57 | 58 | template 59 | struct iterator_traits_helper {}; 60 | 61 | template 62 | struct iterator_traits_helper 63 | : public iterator_traits_impl::value || 65 | std::is_convertible::value> 66 | { 67 | }; 68 | 69 | // 萃取迭代器的特性 70 | template 71 | struct iterator_traits 72 | : public iterator_traits_helper::value> {}; 73 | 74 | // 针对原生指针的偏特化版本 75 | template 76 | struct iterator_traits 77 | { 78 | typedef random_access_iterator_tag iterator_category; 79 | typedef T value_type; 80 | typedef T* pointer; 81 | typedef T& reference; 82 | typedef ptrdiff_t difference_type; 83 | }; 84 | 85 | template 86 | struct iterator_traits 87 | { 88 | typedef random_access_iterator_tag iterator_category; 89 | typedef T value_type; 90 | typedef const T* pointer; 91 | typedef const T& reference; 92 | typedef ptrdiff_t difference_type; 93 | }; 94 | 95 | template >::value> 96 | struct has_iterator_cat_of 97 | : public m_bool_constant::iterator_category, U>::value> 99 | { 100 | }; 101 | 102 | // 萃取某种迭代器 103 | template 104 | struct has_iterator_cat_of : public m_false_type {}; 105 | 106 | template 107 | struct is_exactly_input_iterator : public m_bool_constant::value && 108 | !has_iterator_cat_of::value> {}; 109 | 110 | template 111 | struct is_input_iterator : public has_iterator_cat_of {}; 112 | 113 | template 114 | struct is_output_iterator : public has_iterator_cat_of {}; 115 | 116 | template 117 | struct is_forward_iterator : public has_iterator_cat_of {}; 118 | 119 | template 120 | struct is_bidirectional_iterator : public has_iterator_cat_of {}; 121 | 122 | template 123 | struct is_random_access_iterator : public has_iterator_cat_of {}; 124 | 125 | template 126 | struct is_iterator : 127 | public m_bool_constant::value || 128 | is_output_iterator::value> 129 | { 130 | }; 131 | 132 | // 萃取某个迭代器的 category 133 | template 134 | typename iterator_traits::iterator_category 135 | iterator_category(const Iterator&) 136 | { 137 | typedef typename iterator_traits::iterator_category Category; 138 | return Category(); 139 | } 140 | 141 | // 萃取某个迭代器的 distance_type 142 | template 143 | typename iterator_traits::difference_type* 144 | distance_type(const Iterator&) 145 | { 146 | return static_cast::difference_type*>(0); 147 | } 148 | 149 | // 萃取某个迭代器的 value_type 150 | template 151 | typename iterator_traits::value_type* 152 | value_type(const Iterator&) 153 | { 154 | return static_cast::value_type*>(0); 155 | } 156 | 157 | // 以下函数用于计算迭代器间的距离 158 | 159 | // distance 的 input_iterator_tag 的版本 160 | template 161 | typename iterator_traits::difference_type 162 | distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag) 163 | { 164 | typename iterator_traits::difference_type n = 0; 165 | while (first != last) 166 | { 167 | ++first; 168 | ++n; 169 | } 170 | return n; 171 | } 172 | 173 | // distance 的 random_access_iterator_tag 的版本 174 | template 175 | typename iterator_traits::difference_type 176 | distance_dispatch(RandomIter first, RandomIter last, 177 | random_access_iterator_tag) 178 | { 179 | return last - first; 180 | } 181 | 182 | template 183 | typename iterator_traits::difference_type 184 | distance(InputIterator first, InputIterator last) 185 | { 186 | return distance_dispatch(first, last, iterator_category(first)); 187 | } 188 | 189 | // 以下函数用于让迭代器前进 n 个距离 190 | 191 | // advance 的 input_iterator_tag 的版本 192 | template 193 | void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag) 194 | { 195 | while (n--) 196 | ++i; 197 | } 198 | 199 | // advance 的 bidirectional_iterator_tag 的版本 200 | template 201 | void advance_dispatch(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) 202 | { 203 | if (n >= 0) 204 | while (n--) ++i; 205 | else 206 | while (n++) --i; 207 | } 208 | 209 | // advance 的 random_access_iterator_tag 的版本 210 | template 211 | void advance_dispatch(RandomIter& i, Distance n, random_access_iterator_tag) 212 | { 213 | i += n; 214 | } 215 | 216 | template 217 | void advance(InputIterator& i, Distance n) 218 | { 219 | advance_dispatch(i, n, iterator_category(i)); 220 | } 221 | 222 | /*****************************************************************************************/ 223 | 224 | // 模板类 : reverse_iterator 225 | // 代表反向迭代器,使前进为后退,后退为前进 226 | template 227 | class reverse_iterator 228 | { 229 | private: 230 | Iterator current; // 记录对应的正向迭代器 231 | 232 | public: 233 | // 反向迭代器的五种相应型别 234 | typedef typename iterator_traits::iterator_category iterator_category; 235 | typedef typename iterator_traits::value_type value_type; 236 | typedef typename iterator_traits::difference_type difference_type; 237 | typedef typename iterator_traits::pointer pointer; 238 | typedef typename iterator_traits::reference reference; 239 | 240 | typedef Iterator iterator_type; 241 | typedef reverse_iterator self; 242 | 243 | public: 244 | // 构造函数 245 | reverse_iterator() {} 246 | explicit reverse_iterator(iterator_type i) :current(i) {} 247 | reverse_iterator(const self& rhs) :current(rhs.current) {} 248 | 249 | public: 250 | // 取出对应的正向迭代器 251 | iterator_type base() const 252 | { return current; } 253 | 254 | // 重载操作符 255 | reference operator*() const 256 | { // 实际对应正向迭代器的前一个位置 257 | auto tmp = current; 258 | return *--tmp; 259 | } 260 | pointer operator->() const 261 | { 262 | return &(operator*()); 263 | } 264 | 265 | // 前进(++)变为后退(--) 266 | self& operator++() 267 | { 268 | --current; 269 | return *this; 270 | } 271 | self operator++(int) 272 | { 273 | self tmp = *this; 274 | --current; 275 | return tmp; 276 | } 277 | // 后退(--)变为前进(++) 278 | self& operator--() 279 | { 280 | ++current; 281 | return *this; 282 | } 283 | self operator--(int) 284 | { 285 | self tmp = *this; 286 | ++current; 287 | return tmp; 288 | } 289 | 290 | self& operator+=(difference_type n) 291 | { 292 | current -= n; 293 | return *this; 294 | } 295 | self operator+(difference_type n) const 296 | { 297 | return self(current - n); 298 | } 299 | self& operator-=(difference_type n) 300 | { 301 | current += n; 302 | return *this; 303 | } 304 | self operator-(difference_type n) const 305 | { 306 | return self(current + n); 307 | } 308 | 309 | reference operator[](difference_type n) const 310 | { 311 | return *(*this + n); 312 | } 313 | }; 314 | 315 | // 重载 operator- 316 | template 317 | typename reverse_iterator::difference_type 318 | operator-(const reverse_iterator& lhs, 319 | const reverse_iterator& rhs) 320 | { 321 | return rhs.base() - lhs.base(); 322 | } 323 | 324 | // 重载比较操作符 325 | template 326 | bool operator==(const reverse_iterator& lhs, 327 | const reverse_iterator& rhs) 328 | { 329 | return lhs.base() == rhs.base(); 330 | } 331 | 332 | template 333 | bool operator<(const reverse_iterator& lhs, 334 | const reverse_iterator& rhs) 335 | { 336 | return rhs.base() < lhs.base(); 337 | } 338 | 339 | template 340 | bool operator!=(const reverse_iterator& lhs, 341 | const reverse_iterator& rhs) 342 | { 343 | return !(lhs == rhs); 344 | } 345 | 346 | template 347 | bool operator>(const reverse_iterator& lhs, 348 | const reverse_iterator& rhs) 349 | { 350 | return rhs < lhs; 351 | } 352 | 353 | template 354 | bool operator<=(const reverse_iterator& lhs, 355 | const reverse_iterator& rhs) 356 | { 357 | return !(rhs < lhs); 358 | } 359 | 360 | template 361 | bool operator>=(const reverse_iterator& lhs, 362 | const reverse_iterator& rhs) 363 | { 364 | return !(lhs < rhs); 365 | } 366 | 367 | } // namespace mystl 368 | 369 | #endif // !MYTINYSTL_ITERATOR_H_ 370 | 371 | -------------------------------------------------------------------------------- /MyTinySTL/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_MEMORY_H_ 2 | #define MYTINYSTL_MEMORY_H_ 3 | 4 | // 这个头文件负责更高级的动态内存管理 5 | // 包含一些基本函数、空间配置器、未初始化的储存空间管理,以及一个模板类 auto_ptr 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "algobase.h" 12 | #include "allocator.h" 13 | #include "construct.h" 14 | #include "uninitialized.h" 15 | 16 | namespace mystl 17 | { 18 | 19 | // 获取对象地址 20 | template 21 | constexpr Tp* address_of(Tp& value) noexcept 22 | { 23 | return &value; 24 | } 25 | 26 | // 获取 / 释放 临时缓冲区 27 | 28 | template 29 | pair get_buffer_helper(ptrdiff_t len, T*) 30 | { 31 | if (len > static_cast(INT_MAX / sizeof(T))) 32 | len = INT_MAX / sizeof(T); 33 | while (len > 0) 34 | { 35 | T* tmp = static_cast(malloc(static_cast(len) * sizeof(T))); 36 | if (tmp) 37 | return pair(tmp, len); 38 | len /= 2; // 申请失败时减少 len 的大小 39 | } 40 | return pair(nullptr, 0); 41 | } 42 | 43 | template 44 | pair get_temporary_buffer(ptrdiff_t len) 45 | { 46 | return get_buffer_helper(len, static_cast(0)); 47 | } 48 | 49 | template 50 | pair get_temporary_buffer(ptrdiff_t len, T*) 51 | { 52 | return get_buffer_helper(len, static_cast(0)); 53 | } 54 | 55 | template 56 | void release_temporary_buffer(T* ptr) 57 | { 58 | free(ptr); 59 | } 60 | 61 | // -------------------------------------------------------------------------------------- 62 | // 类模板 : temporary_buffer 63 | // 进行临时缓冲区的申请与释放 64 | template 65 | class temporary_buffer 66 | { 67 | private: 68 | ptrdiff_t original_len; // 缓冲区申请的大小 69 | ptrdiff_t len; // 缓冲区实际的大小 70 | T* buffer; // 指向缓冲区的指针 71 | 72 | public: 73 | // 构造、析构函数 74 | temporary_buffer(ForwardIterator first, ForwardIterator last); 75 | 76 | ~temporary_buffer() 77 | { 78 | mystl::destroy(buffer, buffer + len); 79 | free(buffer); 80 | } 81 | 82 | public: 83 | 84 | ptrdiff_t size() const noexcept { return len; } 85 | ptrdiff_t requested_size() const noexcept { return original_len; } 86 | T* begin() noexcept { return buffer; } 87 | T* end() noexcept { return buffer + len; } 88 | 89 | private: 90 | void allocate_buffer(); 91 | void initialize_buffer(const T&, std::true_type) {} 92 | void initialize_buffer(const T& value, std::false_type) 93 | { mystl::uninitialized_fill_n(buffer, len, value); } 94 | 95 | private: 96 | temporary_buffer(const temporary_buffer&); 97 | void operator=(const temporary_buffer&); 98 | }; 99 | 100 | // 构造函数 101 | template 102 | temporary_buffer:: 103 | temporary_buffer(ForwardIterator first, ForwardIterator last) 104 | { 105 | try 106 | { 107 | len = mystl::distance(first, last); 108 | allocate_buffer(); 109 | if (len > 0) 110 | { 111 | initialize_buffer(*first, std::is_trivially_default_constructible()); 112 | } 113 | } 114 | catch (...) 115 | { 116 | free(buffer); 117 | buffer = nullptr; 118 | len = 0; 119 | } 120 | } 121 | 122 | // allocate_buffer 函数 123 | template 124 | void temporary_buffer::allocate_buffer() 125 | { 126 | original_len = len; 127 | if (len > static_cast(INT_MAX / sizeof(T))) 128 | len = INT_MAX / sizeof(T); 129 | while (len > 0) 130 | { 131 | buffer = static_cast(malloc(len * sizeof(T))); 132 | if (buffer) 133 | break; 134 | len /= 2; // 申请失败时减少申请空间大小 135 | } 136 | } 137 | 138 | // -------------------------------------------------------------------------------------- 139 | // 模板类: auto_ptr 140 | // 一个具有严格对象所有权的小型智能指针 141 | template 142 | class auto_ptr 143 | { 144 | public: 145 | typedef T elem_type; 146 | 147 | private: 148 | T* m_ptr; // 实际指针 149 | 150 | public: 151 | // 构造、复制、析构函数 152 | explicit auto_ptr(T* p = nullptr) :m_ptr(p) {} 153 | auto_ptr(auto_ptr& rhs) :m_ptr(rhs.release()) {} 154 | template 155 | auto_ptr(auto_ptr& rhs) : m_ptr(rhs.release()) {} 156 | 157 | auto_ptr& operator=(auto_ptr& rhs) 158 | { 159 | if (this != &rhs) 160 | { 161 | delete m_ptr; 162 | m_ptr = rhs.release(); 163 | } 164 | return *this; 165 | } 166 | template 167 | auto_ptr& operator=(auto_ptr& rhs) 168 | { 169 | if (this->get() != rhs.get()) 170 | { 171 | delete m_ptr; 172 | m_ptr = rhs.release(); 173 | } 174 | return *this; 175 | } 176 | 177 | ~auto_ptr() { delete m_ptr; } 178 | 179 | public: 180 | // 重载 operator* 和 operator-> 181 | T& operator*() const { return *m_ptr; } 182 | T* operator->() const { return m_ptr; } 183 | 184 | // 获得指针 185 | T* get() const { return m_ptr; } 186 | 187 | // 释放指针 188 | T* release() 189 | { 190 | T* tmp = m_ptr; 191 | m_ptr = nullptr; 192 | return tmp; 193 | } 194 | 195 | // 重置指针 196 | void reset(T* p = nullptr) 197 | { 198 | if (m_ptr != p) 199 | { 200 | delete m_ptr; 201 | m_ptr = p; 202 | } 203 | } 204 | }; 205 | 206 | } // namespace mystl 207 | #endif // !MYTINYSTL_MEMORY_H_ 208 | 209 | -------------------------------------------------------------------------------- /MyTinySTL/numeric.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_NUMERIC_H_ 2 | #define MYTINYSTL_NUMERIC_H_ 3 | 4 | // 这个头文件包含了 mystl 的数值算法 5 | 6 | #include "iterator.h" 7 | 8 | namespace mystl 9 | { 10 | 11 | /*****************************************************************************************/ 12 | // accumulate 13 | // 版本1:以初值 init 对每个元素进行累加 14 | // 版本2:以初值 init 对每个元素进行二元操作 15 | /*****************************************************************************************/ 16 | // 版本1 17 | template 18 | T accumulate(InputIter first, InputIter last, T init) 19 | { 20 | for (; first != last; ++first) 21 | { 22 | init += *first; 23 | } 24 | return init; 25 | } 26 | 27 | // 版本2 28 | template 29 | T accumulate(InputIter first, InputIter last, T init, BinaryOp binary_op) 30 | { 31 | for (; first != last; ++first) 32 | { 33 | init = binary_op(init, *first); 34 | } 35 | return init; 36 | } 37 | 38 | /*****************************************************************************************/ 39 | // adjacent_difference 40 | // 版本1:计算相邻元素的差值,结果保存到以 result 为起始的区间上 41 | // 版本2:自定义相邻元素的二元操作 42 | /*****************************************************************************************/ 43 | // 版本1 44 | template 45 | OutputIter adjacent_difference(InputIter first, InputIter last, OutputIter result) 46 | { 47 | if (first == last) return result; 48 | *result = *first; // 记录第一个元素 49 | auto value = *first; 50 | while (++first != last) 51 | { 52 | auto tmp = *first; 53 | *++result = tmp - value; 54 | value = tmp; 55 | } 56 | return ++result; 57 | } 58 | 59 | // 版本2 60 | template 61 | OutputIter adjacent_difference(InputIter first, InputIter last, OutputIter result, 62 | BinaryOp binary_op) 63 | { 64 | if (first == last) return result; 65 | *result = *first; // 记录第一个元素 66 | auto value = *first; 67 | while (++first != last) 68 | { 69 | auto tmp = *first; 70 | *++result = binary_op(tmp, value); 71 | value = tmp; 72 | } 73 | return ++result; 74 | } 75 | 76 | /*****************************************************************************************/ 77 | // inner_product 78 | // 版本1:以 init 为初值,计算两个区间的内积 79 | // 版本2:自定义 operator+ 和 operator* 80 | /*****************************************************************************************/ 81 | // 版本1 82 | template 83 | T inner_product(InputIter1 first1, InputIter1 last1, InputIter2 first2, T init) 84 | { 85 | for (; first1 != last1; ++first1, ++first2) 86 | { 87 | init = init + (*first1 * *first2); 88 | } 89 | return init; 90 | } 91 | 92 | // 版本2 93 | template 94 | T inner_product(InputIter1 first1, InputIter1 last1, InputIter2 first2, T init, 95 | BinaryOp1 binary_op1, BinaryOp2 binary_op2) 96 | { 97 | for (; first1 != last1; ++first1, ++first2) 98 | { 99 | init = binary_op1(init, binary_op2(*first1, *first2)); 100 | } 101 | return init; 102 | } 103 | 104 | /*****************************************************************************************/ 105 | // iota 106 | // 填充[first, last),以 value 为初值开始递增 107 | /*****************************************************************************************/ 108 | template 109 | void iota(ForwardIter first, ForwardIter last, T value) 110 | { 111 | while (first != last) 112 | { 113 | *first++ = value; 114 | ++value; 115 | } 116 | } 117 | 118 | /*****************************************************************************************/ 119 | // partial_sum 120 | // 版本1:计算局部累计求和,结果保存到以 result 为起始的区间上 121 | // 版本2:进行局部进行自定义二元操作 122 | /*****************************************************************************************/ 123 | template 124 | OutputIter partial_sum(InputIter first, InputIter last, OutputIter result) 125 | { 126 | if (first == last) return result; 127 | *result = *first; // 记录第一个元素 128 | auto value = *first; 129 | while (++first != last) 130 | { 131 | value = value + *first; 132 | *++result = value; 133 | } 134 | return ++result; 135 | } 136 | 137 | // 版本2 138 | template 139 | OutputIter partial_sum(InputIter first, InputIter last, OutputIter result, 140 | BinaryOp binary_op) 141 | { 142 | if (first == last) return result; 143 | *result = *first; //记录第一个元素 144 | auto value = *first; 145 | while (++first != last) 146 | { 147 | value = binary_op(value, *first); 148 | *++result = value; 149 | } 150 | return ++result; 151 | } 152 | 153 | } // namespace mystl 154 | #endif // !MYTINYSTL_NUMERIC_H_ 155 | 156 | -------------------------------------------------------------------------------- /MyTinySTL/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_QUEUE_H_ 2 | #define MYTINYSTL_QUEUE_H_ 3 | 4 | // 这个头文件包含了两个模板类 queue 和 priority_queue 5 | // queue : 队列 6 | // priority_queue : 优先队列 7 | 8 | #include "deque.h" 9 | #include "vector.h" 10 | #include "functional.h" 11 | #include "heap_algo.h" 12 | 13 | namespace mystl 14 | { 15 | 16 | // 模板类 queue 17 | // 参数一代表数据类型,参数二代表底层容器类型,缺省使用 mystl::deque 作为底层容器 18 | template > 19 | class queue 20 | { 21 | public: 22 | typedef Container container_type; 23 | // 使用底层容器的型别 24 | typedef typename Container::value_type value_type; 25 | typedef typename Container::size_type size_type; 26 | typedef typename Container::reference reference; 27 | typedef typename Container::const_reference const_reference; 28 | 29 | static_assert(std::is_same::value, 30 | "the value_type of Container should be same with T"); 31 | private: 32 | container_type c_; // 用底层容器表现 queue 33 | 34 | public: 35 | // 构造、复制、移动函数 36 | 37 | queue() = default; 38 | 39 | explicit queue(size_type n) 40 | :c_(n) 41 | { 42 | } 43 | queue(size_type n, const value_type& value) 44 | :c_(n, value) 45 | { 46 | } 47 | 48 | template 49 | queue(IIter first, IIter last) 50 | :c_(first, last) 51 | { 52 | } 53 | 54 | queue(std::initializer_list ilist) 55 | :c_(ilist.begin(), ilist.end()) 56 | { 57 | } 58 | 59 | queue(const Container& c) 60 | :c_(c) 61 | { 62 | } 63 | queue(Container&& c) noexcept(std::is_nothrow_move_constructible::value) 64 | :c_(mystl::move(c)) 65 | { 66 | } 67 | 68 | queue(const queue& rhs) 69 | :c_(rhs.c_) 70 | { 71 | } 72 | queue(queue&& rhs) noexcept(std::is_nothrow_move_constructible::value) 73 | :c_(mystl::move(rhs.c_)) 74 | { 75 | } 76 | 77 | queue& operator=(const queue& rhs) 78 | { 79 | c_ = rhs.c_; 80 | return *this; 81 | } 82 | queue& operator=(queue&& rhs) noexcept(std::is_nothrow_move_assignable::value) 83 | { 84 | c_ = mystl::move(rhs.c_); 85 | return *this; 86 | } 87 | 88 | queue& operator=(std::initializer_list ilist) 89 | { 90 | c_ = ilist; 91 | return *this; 92 | } 93 | 94 | ~queue() = default; 95 | 96 | // 访问元素相关操作 97 | reference front() { return c_.front(); } 98 | const_reference front() const { return c_.front(); } 99 | reference back() { return c_.back(); } 100 | const_reference back() const { return c_.back(); } 101 | 102 | // 容量相关操作 103 | bool empty() const noexcept { return c_.empty(); } 104 | size_type size() const noexcept { return c_.size(); } 105 | 106 | // 修改容器相关操作 107 | template 108 | void emplace(Args&& ...args) 109 | { c_.emplace_back(mystl::forward(args)...); } 110 | 111 | void push(const value_type& value) 112 | { c_.push_back(value); } 113 | void push(value_type&& value) 114 | { c_.emplace_back(mystl::move(value)); } 115 | 116 | void pop() 117 | { c_.pop_front(); } 118 | 119 | void clear() 120 | { 121 | while (!empty()) 122 | pop(); 123 | } 124 | 125 | void swap(queue& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_))) 126 | { mystl::swap(c_, rhs.c_); } 127 | 128 | public: 129 | friend bool operator==(const queue& lhs, const queue& rhs) { return lhs.c_ == rhs.c_; } 130 | friend bool operator< (const queue& lhs, const queue& rhs) { return lhs.c_ < rhs.c_; } 131 | }; 132 | 133 | // 重载比较操作符 134 | template 135 | bool operator==(const queue& lhs, const queue& rhs) 136 | { 137 | return lhs == rhs; 138 | } 139 | 140 | template 141 | bool operator!=(const queue& lhs, const queue& rhs) 142 | { 143 | return !(lhs == rhs); 144 | } 145 | 146 | template 147 | bool operator<(const queue& lhs, const queue& rhs) 148 | { 149 | return lhs < rhs; 150 | } 151 | 152 | template 153 | bool operator>(const queue& lhs, const queue& rhs) 154 | { 155 | return rhs < lhs; 156 | } 157 | 158 | template 159 | bool operator<=(const queue& lhs, const queue& rhs) 160 | { 161 | return !(rhs < lhs); 162 | } 163 | 164 | template 165 | bool operator>=(const queue& lhs, const queue& rhs) 166 | { 167 | return !(lhs < rhs); 168 | } 169 | 170 | // 重载 mystl 的 swap 171 | template 172 | void swap(queue& lhs, queue& rhs) noexcept(noexcept(lhs.swap(rhs))) 173 | { 174 | lhs.swap(rhs); 175 | } 176 | 177 | /*****************************************************************************************/ 178 | 179 | // 模板类 priority_queue 180 | // 参数一代表数据类型,参数二代表容器类型,缺省使用 mystl::vector 作为底层容器 181 | // 参数三代表比较权值的方式,缺省使用 mystl::less 作为比较方式 182 | template , 183 | class Compare = mystl::less> 184 | class priority_queue 185 | { 186 | public: 187 | typedef Container container_type; 188 | typedef Compare value_compare; 189 | // 使用底层容器的型别 190 | typedef typename Container::value_type value_type; 191 | typedef typename Container::size_type size_type; 192 | typedef typename Container::reference reference; 193 | typedef typename Container::const_reference const_reference; 194 | 195 | static_assert(std::is_same::value, 196 | "the value_type of Container should be same with T"); 197 | 198 | private: 199 | container_type c_; // 用底层容器来表现 priority_queue 200 | value_compare comp_; // 权值比较的标准 201 | 202 | public: 203 | // 构造、复制、移动函数 204 | priority_queue() = default; 205 | 206 | priority_queue(const Compare& c) 207 | :c_(), comp_(c) 208 | { 209 | } 210 | 211 | explicit priority_queue(size_type n) 212 | :c_(n) 213 | { 214 | mystl::make_heap(c_.begin(), c_.end(), comp_); 215 | } 216 | priority_queue(size_type n, const value_type& value) 217 | :c_(n, value) 218 | { 219 | mystl::make_heap(c_.begin(), c_.end(), comp_); 220 | } 221 | 222 | template 223 | priority_queue(IIter first, IIter last) 224 | :c_(first, last) 225 | { 226 | mystl::make_heap(c_.begin(), c_.end(), comp_); 227 | } 228 | 229 | priority_queue(std::initializer_list ilist) 230 | :c_(ilist) 231 | { 232 | mystl::make_heap(c_.begin(), c_.end(), comp_); 233 | } 234 | 235 | priority_queue(const Container& s) 236 | :c_(s) 237 | { 238 | mystl::make_heap(c_.begin(), c_.end(), comp_); 239 | } 240 | priority_queue(Container&& s) 241 | :c_(mystl::move(s)) 242 | { 243 | mystl::make_heap(c_.begin(), c_.end(), comp_); 244 | } 245 | 246 | priority_queue(const priority_queue& rhs) 247 | :c_(rhs.c_), comp_(rhs.comp_) 248 | { 249 | mystl::make_heap(c_.begin(), c_.end(), comp_); 250 | } 251 | priority_queue(priority_queue&& rhs) 252 | :c_(mystl::move(rhs.c_)), comp_(rhs.comp_) 253 | { 254 | mystl::make_heap(c_.begin(), c_.end(), comp_); 255 | } 256 | 257 | priority_queue& operator=(const priority_queue& rhs) 258 | { 259 | c_ = rhs.c_; 260 | comp_ = rhs.comp_; 261 | mystl::make_heap(c_.begin(), c_.end(), comp_); 262 | return *this; 263 | } 264 | priority_queue& operator=(priority_queue&& rhs) 265 | { 266 | c_ = mystl::move(rhs.c_); 267 | comp_ = rhs.comp_; 268 | mystl::make_heap(c_.begin(), c_.end(), comp_); 269 | return *this; 270 | } 271 | priority_queue& operator=(std::initializer_list ilist) 272 | { 273 | c_ = ilist; 274 | comp_ = value_compare(); 275 | mystl::make_heap(c_.begin(), c_.end(), comp_); 276 | return *this; 277 | } 278 | 279 | ~priority_queue() = default; 280 | 281 | public: 282 | 283 | // 访问元素相关操作 284 | const_reference top() const { return c_.front(); } 285 | 286 | // 容量相关操作 287 | bool empty() const noexcept { return c_.empty(); } 288 | size_type size() const noexcept { return c_.size(); } 289 | 290 | // 修改容器相关操作 291 | template 292 | void emplace(Args&& ...args) 293 | { 294 | c_.emplace_back(mystl::forward(args)...); 295 | mystl::push_heap(c_.begin(), c_.end(), comp_); 296 | } 297 | 298 | void push(const value_type& value) 299 | { 300 | c_.push_back(value); 301 | mystl::push_heap(c_.begin(), c_.end(), comp_); 302 | } 303 | void push(value_type&& value) 304 | { 305 | c_.push_back(mystl::move(value)); 306 | mystl::push_heap(c_.begin(), c_.end(), comp_); 307 | } 308 | 309 | void pop() 310 | { 311 | mystl::pop_heap(c_.begin(), c_.end(), comp_); 312 | c_.pop_back(); 313 | } 314 | 315 | void clear() 316 | { 317 | while (!empty()) 318 | pop(); 319 | } 320 | 321 | void swap(priority_queue& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_)) && 322 | noexcept(mystl::swap(comp_, rhs.comp_))) 323 | { 324 | mystl::swap(c_, rhs.c_); 325 | mystl::swap(comp_, rhs.comp_); 326 | } 327 | 328 | public: 329 | friend bool operator==(const priority_queue& lhs, const priority_queue& rhs) 330 | { 331 | return lhs.c_ == rhs.c_; 332 | } 333 | friend bool operator!=(const priority_queue& lhs, const priority_queue& rhs) 334 | { 335 | return lhs.c_ != rhs.c_; 336 | } 337 | }; 338 | 339 | // 重载比较操作符 340 | template 341 | bool operator==(priority_queue& lhs, 342 | priority_queue& rhs) 343 | { 344 | return lhs == rhs; 345 | } 346 | 347 | template 348 | bool operator!=(priority_queue& lhs, 349 | priority_queue& rhs) 350 | { 351 | return lhs != rhs; 352 | } 353 | 354 | // 重载 mystl 的 swap 355 | template 356 | void swap(priority_queue& lhs, 357 | priority_queue& rhs) noexcept(noexcept(lhs.swap(rhs))) 358 | { 359 | lhs.swap(rhs); 360 | } 361 | 362 | } // namespace mystl 363 | #endif // !MYTINYSTL_QUEUE_H_ 364 | 365 | -------------------------------------------------------------------------------- /MyTinySTL/set_algo.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_SET_ALGO_H_ 2 | #define MYTINYSTL_SET_ALGO_H_ 3 | 4 | // 这个头文件包含 set 的四种算法: union, intersection, difference, symmetric_difference 5 | // 所有函数都要求序列有序 6 | 7 | #include "algobase.h" 8 | #include "iterator.h" 9 | 10 | namespace mystl 11 | { 12 | 13 | /*****************************************************************************************/ 14 | // set_union 15 | // 计算 S1∪S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 16 | /*****************************************************************************************/ 17 | template 18 | OutputIter set_union(InputIter1 first1, InputIter1 last1, 19 | InputIter2 first2, InputIter2 last2, 20 | OutputIter result) 21 | { 22 | while (first1 != last1 && first2 != last2) 23 | { 24 | if (*first1 < *first2) 25 | { 26 | *result = *first1; 27 | ++first1; 28 | } 29 | else if (*first2 < *first1) 30 | { 31 | *result = *first2; 32 | ++first2; 33 | } 34 | else 35 | { 36 | *result = *first1; 37 | ++first1; 38 | ++first2; 39 | } 40 | ++result; 41 | } 42 | // 将剩余元素拷贝到 result 43 | return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); 44 | } 45 | 46 | // 重载版本使用函数对象 comp 代替比较操作 47 | template 48 | OutputIter set_union(InputIter1 first1, InputIter1 last1, 49 | InputIter2 first2, InputIter2 last2, 50 | OutputIter result, Compared comp) 51 | { 52 | while (first1 != last1 && first2 != last2) 53 | { 54 | if (comp(*first1, *first2)) 55 | { 56 | *result = *first1; 57 | ++first1; 58 | } 59 | else if (comp(*first2, *first1)) 60 | { 61 | *result = *first2; 62 | ++first2; 63 | } 64 | else 65 | { 66 | *result = *first1; 67 | ++first1; 68 | ++first2; 69 | } 70 | ++result; 71 | } 72 | // 将剩余元素拷贝到 result 73 | return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); 74 | } 75 | 76 | /*****************************************************************************************/ 77 | // set_intersection 78 | // 计算 S1∩S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 79 | /*****************************************************************************************/ 80 | template 81 | OutputIter set_intersection(InputIter1 first1, InputIter1 last1, 82 | InputIter2 first2, InputIter2 last2, 83 | OutputIter result) 84 | { 85 | while (first1 != last1 && first2 != last2) 86 | { 87 | if (*first1 < *first2) 88 | { 89 | ++first1; 90 | } 91 | else if (*first2 < *first1) 92 | { 93 | ++first2; 94 | } 95 | else 96 | { 97 | *result = *first1; 98 | ++first1; 99 | ++first2; 100 | ++result; 101 | } 102 | } 103 | return result; 104 | } 105 | 106 | // 重载版本使用函数对象 comp 代替比较操作 107 | template 108 | OutputIter set_intersection(InputIter1 first1, InputIter1 last1, 109 | InputIter2 first2, InputIter2 last2, 110 | OutputIter result, Compared comp) 111 | { 112 | while (first1 != last1 && first2 != last2) 113 | { 114 | if (comp(*first1, *first2)) 115 | { 116 | ++first1; 117 | } 118 | else if (comp(*first2, *first1)) 119 | { 120 | ++first2; 121 | } 122 | else 123 | { 124 | *result = *first1; 125 | ++first1; 126 | ++first2; 127 | ++result; 128 | } 129 | } 130 | return result; 131 | } 132 | 133 | /*****************************************************************************************/ 134 | // set_difference 135 | // 计算 S1-S2 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 136 | /*****************************************************************************************/ 137 | template 138 | OutputIter set_difference(InputIter1 first1, InputIter1 last1, 139 | InputIter2 first2, InputIter2 last2, 140 | OutputIter result) 141 | { 142 | while (first1 != last1 && first2 != last2) 143 | { 144 | if (*first1 < *first2) 145 | { 146 | *result = *first1; 147 | ++first1; 148 | ++result; 149 | } 150 | else if (*first2 < *first1) 151 | { 152 | ++first2; 153 | } 154 | else 155 | { 156 | ++first1; 157 | ++first2; 158 | } 159 | } 160 | return mystl::copy(first1, last1, result); 161 | } 162 | 163 | // 重载版本使用函数对象 comp 代替比较操作 164 | template 165 | OutputIter set_difference(InputIter1 first1, InputIter1 last1, 166 | InputIter2 first2, InputIter2 last2, 167 | OutputIter result, Compared comp) 168 | { 169 | while (first1 != last1 && first2 != last2) 170 | { 171 | if (comp(*first1, *first2)) 172 | { 173 | *result = *first1; 174 | ++first1; 175 | ++result; 176 | } 177 | else if (comp(*first2, *first1)) 178 | { 179 | ++first2; 180 | } 181 | else 182 | { 183 | ++first1; 184 | ++first2; 185 | } 186 | } 187 | return mystl::copy(first1, last1, result); 188 | } 189 | 190 | /*****************************************************************************************/ 191 | // set_symmetric_difference 192 | // 计算 (S1-S2)∪(S2-S1) 的结果并保存到 result 中,返回一个迭代器指向输出结果的尾部 193 | /*****************************************************************************************/ 194 | template 195 | OutputIter set_symmetric_difference(InputIter1 first1, InputIter1 last1, 196 | InputIter2 first2, InputIter2 last2, 197 | OutputIter result) 198 | { 199 | while (first1 != last1 && first2 != last2) 200 | { 201 | if (*first1 < *first2) 202 | { 203 | *result = *first1; 204 | ++first1; 205 | ++result; 206 | } 207 | else if (*first2 < *first1) 208 | { 209 | *result = *first2; 210 | ++first2; 211 | ++result; 212 | } 213 | else 214 | { 215 | ++first1; 216 | ++first2; 217 | } 218 | } 219 | return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); 220 | } 221 | 222 | // 重载版本使用函数对象 comp 代替比较操作 223 | template 224 | OutputIter set_symmetric_difference(InputIter1 first1, InputIter1 last1, 225 | InputIter2 first2, InputIter2 last2, 226 | OutputIter result, Compared comp) 227 | { 228 | while (first1 != last1 && first2 != last2) 229 | { 230 | if (comp(*first1, *first2)) 231 | { 232 | *result = *first1; 233 | ++first1; 234 | ++result; 235 | } 236 | else if (comp(*first2, *first1)) 237 | { 238 | *result = *first2; 239 | ++first2; 240 | ++result; 241 | } 242 | else 243 | { 244 | ++first1; 245 | ++first2; 246 | } 247 | } 248 | return mystl::copy(first2, last2, mystl::copy(first1, last1, result)); 249 | } 250 | 251 | } // namespace mystl 252 | #endif // !MYTINYSTL_SET_ALGO_H_ 253 | 254 | -------------------------------------------------------------------------------- /MyTinySTL/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_STACK_H_ 2 | #define MYTINYSTL_STACK_H_ 3 | 4 | // 这个头文件包含了一个模板类 stack 5 | // stack : 栈 6 | 7 | #include "deque.h" 8 | 9 | namespace mystl 10 | { 11 | 12 | // 模板类 stack 13 | // 参数一代表数据类型,参数二代表底层容器类型,缺省使用 mystl::deque 作为底层容器 14 | template > 15 | class stack 16 | { 17 | public: 18 | typedef Container container_type; 19 | // 使用底层容器的型别 20 | typedef typename Container::value_type value_type; 21 | typedef typename Container::size_type size_type; 22 | typedef typename Container::reference reference; 23 | typedef typename Container::const_reference const_reference; 24 | 25 | static_assert(std::is_same::value, 26 | "the value_type of Container should be same with T"); 27 | private: 28 | container_type c_; // 用底层容器表现 stack 29 | 30 | public: 31 | // 构造、复制、移动函数 32 | stack() = default; 33 | 34 | explicit stack(size_type n) 35 | :c_(n) 36 | { 37 | } 38 | stack(size_type n, const value_type& value) 39 | :c_(n, value) 40 | { 41 | } 42 | 43 | template 44 | stack(IIter first, IIter last) 45 | : c_(first, last) 46 | { 47 | } 48 | 49 | stack(std::initializer_list ilist) 50 | :c_(ilist.begin(), ilist.end()) 51 | { 52 | } 53 | 54 | stack(const Container& c) 55 | :c_(c) 56 | { 57 | } 58 | stack(Container&& c) noexcept(std::is_nothrow_move_constructible::value) 59 | :c_(mystl::move(c)) 60 | { 61 | } 62 | 63 | stack(const stack& rhs) 64 | :c_(rhs.c_) 65 | { 66 | } 67 | stack(stack&& rhs) noexcept(std::is_nothrow_move_constructible::value) 68 | :c_(mystl::move(rhs.c_)) 69 | { 70 | } 71 | 72 | stack& operator=(const stack& rhs) 73 | { 74 | c_ = rhs.c_; 75 | return *this; 76 | } 77 | stack& operator=(stack&& rhs) noexcept(std::is_nothrow_move_assignable::value) 78 | { 79 | c_ = mystl::move(rhs.c_); 80 | return *this; 81 | } 82 | 83 | stack& operator=(std::initializer_list ilist) 84 | { 85 | c_ = ilist; 86 | return *this; 87 | } 88 | 89 | ~stack() = default; 90 | 91 | // 访问元素相关操作 92 | reference top() { return c_.back(); } 93 | const_reference top() const { return c_.back(); } 94 | 95 | // 容量相关操作 96 | bool empty() const noexcept { return c_.empty(); } 97 | size_type size() const noexcept { return c_.size(); } 98 | 99 | // 修改容器相关操作 100 | 101 | template 102 | void emplace(Args&& ...args) 103 | { c_.emplace_back(mystl::forward(args)...); } 104 | 105 | void push(const value_type& value) 106 | { c_.push_back(value); } 107 | void push(value_type&& value) 108 | { c_.push_back(mystl::move(value)); } 109 | 110 | void pop() 111 | { c_.pop_back(); } 112 | 113 | void clear() 114 | { 115 | while (!empty()) 116 | pop(); 117 | } 118 | 119 | void swap(stack& rhs) noexcept(noexcept(mystl::swap(c_, rhs.c_))) 120 | { mystl::swap(c_, rhs.c_); } 121 | 122 | public: 123 | friend bool operator==(const stack& lhs, const stack& rhs) { return lhs.c_ == rhs.c_; } 124 | friend bool operator< (const stack& lhs, const stack& rhs) { return lhs.c_ < rhs.c_; } 125 | }; 126 | 127 | // 重载比较操作符 128 | template 129 | bool operator==(const stack& lhs, const stack& rhs) 130 | { 131 | return lhs == rhs; 132 | } 133 | 134 | template 135 | bool operator<(const stack& lhs, const stack& rhs) 136 | { 137 | return lhs < rhs; 138 | } 139 | 140 | template 141 | bool operator!=(const stack& lhs, const stack& rhs) 142 | { 143 | return !(lhs == rhs); 144 | } 145 | 146 | template 147 | bool operator>(const stack& lhs, const stack& rhs) 148 | { 149 | return rhs < lhs; 150 | } 151 | 152 | template 153 | bool operator<=(const stack& lhs, const stack& rhs) 154 | { 155 | return !(rhs < lhs); 156 | } 157 | 158 | template 159 | bool operator>=(const stack& lhs, const stack& rhs) 160 | { 161 | return !(lhs < rhs); 162 | } 163 | 164 | // 重载 mystl 的 swap 165 | template 166 | void swap(stack& lhs, stack& rhs) noexcept(noexcept(lhs.swap(rhs))) 167 | { 168 | lhs.swap(rhs); 169 | } 170 | 171 | } // namespace mystl 172 | #endif // !MYTINYSTL_STACK_H_ 173 | 174 | -------------------------------------------------------------------------------- /MyTinySTL/stream_iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_STREAM_ITERATOR_H_ 2 | #define MYTINYSTL_STREAM_ITERATOR_H_ 3 | 4 | #include "basic_string.h" 5 | 6 | namespace mystl 7 | { 8 | 9 | template, typename Dist = ptrdiff_t> 11 | class istream_iterator 12 | : public iterator 13 | { 14 | public: 15 | using char_type = CharT; 16 | using traits_type = Traits; 17 | using istream_type = std::basic_istream; 18 | 19 | istream_iterator() /* noexcept(std::is_nothrow_default_constructible::value) */ 20 | : m_stream{nullptr}, m_value{} {} 21 | 22 | istream_iterator(istream_type& is) 23 | : m_stream{std::addressof(is)} 24 | { read(); } 25 | 26 | istream_iterator(const istream_iterator& other) /* noexcept(std::is_nothrow_copy_constructible::value) */ 27 | = default; // memberwise copy 28 | 29 | istream_iterator& operator=(const istream_iterator&) = default; // memberwise copy-asgn 30 | 31 | ~istream_iterator() = default; 32 | 33 | const T& operator*() const noexcept { 34 | MYSTL_DEBUG(m_stream != nullptr); 35 | return m_value; 36 | } 37 | 38 | const T* operator->() const noexcept { 39 | return std::addressof(*this); 40 | } 41 | 42 | istream_iterator& operator++() { 43 | MYSTL_DEBUG(m_stream != nullptr); 44 | read(); 45 | return *this; 46 | } 47 | 48 | istream_iterator operator++(int) { 49 | auto tmp = *this; 50 | ++*this; 51 | return tmp; 52 | } 53 | 54 | private: 55 | istream_type* m_stream; 56 | T m_value; 57 | 58 | void read() { 59 | if (m_stream && !(*m_stream >> m_value)) { // m_stream 有效且读到 EOS 60 | m_stream = nullptr; 61 | } 62 | } 63 | 64 | friend bool operator==(const istream_iterator& lhs, const istream_iterator& rhs) { 65 | return lhs.m_stream == rhs.m_stream; 66 | } 67 | 68 | friend bool operator!=(const istream_iterator& lhs, const istream_iterator& rhs) { 69 | return lhs.m_stream != rhs.m_stream; 70 | } 71 | }; 72 | 73 | 74 | // TODO 75 | // template > 77 | // class ostream_iterator : public iterator {}; 78 | } 79 | 80 | 81 | #endif -------------------------------------------------------------------------------- /MyTinySTL/type_traits.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_TYPE_TRAITS_H_ 2 | #define MYTINYSTL_TYPE_TRAITS_H_ 3 | 4 | // 这个头文件用于提取类型信息 5 | 6 | // use standard header for type_traits 7 | #include 8 | 9 | namespace mystl 10 | { 11 | 12 | // helper struct 13 | 14 | template 15 | struct m_integral_constant 16 | { 17 | static constexpr T value = v; 18 | }; 19 | 20 | template 21 | using m_bool_constant = m_integral_constant; 22 | 23 | typedef m_bool_constant m_true_type; 24 | typedef m_bool_constant m_false_type; 25 | 26 | /*****************************************************************************************/ 27 | // type traits 28 | 29 | // is_pair 30 | 31 | // --- forward declaration begin 32 | template 33 | struct pair; 34 | // --- forward declaration end 35 | 36 | template 37 | struct is_pair : mystl::m_false_type {}; 38 | 39 | template 40 | struct is_pair> : mystl::m_true_type {}; 41 | 42 | } // namespace mystl 43 | 44 | #endif // !MYTINYSTL_TYPE_TRAITS_H_ 45 | 46 | -------------------------------------------------------------------------------- /MyTinySTL/uninitialized.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_UNINITIALIZED_H_ 2 | #define MYTINYSTL_UNINITIALIZED_H_ 3 | 4 | // 这个头文件用于对未初始化空间构造元素 5 | 6 | #include "algobase.h" 7 | #include "construct.h" 8 | #include "iterator.h" 9 | #include "type_traits.h" 10 | #include "util.h" 11 | 12 | namespace mystl 13 | { 14 | 15 | /*****************************************************************************************/ 16 | // uninitialized_copy 17 | // 把 [first, last) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置 18 | /*****************************************************************************************/ 19 | template 20 | ForwardIter 21 | unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::true_type) 22 | { 23 | return mystl::copy(first, last, result); 24 | } 25 | 26 | template 27 | ForwardIter 28 | unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::false_type) 29 | { 30 | auto cur = result; 31 | try 32 | { 33 | for (; first != last; ++first, ++cur) 34 | { 35 | mystl::construct(&*cur, *first); 36 | } 37 | } 38 | catch (...) 39 | { 40 | for (; result != cur; --cur) 41 | mystl::destroy(&*cur); 42 | } 43 | return cur; 44 | } 45 | 46 | template 47 | ForwardIter uninitialized_copy(InputIter first, InputIter last, ForwardIter result) 48 | { 49 | return mystl::unchecked_uninit_copy(first, last, result, 50 | std::is_trivially_copy_assignable< 51 | typename iterator_traits:: 52 | value_type>{}); 53 | } 54 | 55 | /*****************************************************************************************/ 56 | // uninitialized_copy_n 57 | // 把 [first, first + n) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置 58 | /*****************************************************************************************/ 59 | template 60 | ForwardIter 61 | unchecked_uninit_copy_n(InputIter first, Size n, ForwardIter result, std::true_type) 62 | { 63 | return mystl::copy_n(first, n, result).second; 64 | } 65 | 66 | template 67 | ForwardIter 68 | unchecked_uninit_copy_n(InputIter first, Size n, ForwardIter result, std::false_type) 69 | { 70 | auto cur = result; 71 | try 72 | { 73 | for (; n > 0; --n, ++cur, ++first) 74 | { 75 | mystl::construct(&*cur, *first); 76 | } 77 | } 78 | catch (...) 79 | { 80 | for (; result != cur; --cur) 81 | mystl::destroy(&*cur); 82 | } 83 | return cur; 84 | } 85 | 86 | template 87 | ForwardIter uninitialized_copy_n(InputIter first, Size n, ForwardIter result) 88 | { 89 | return mystl::unchecked_uninit_copy_n(first, n, result, 90 | std::is_trivially_copy_assignable< 91 | typename iterator_traits:: 92 | value_type>{}); 93 | } 94 | 95 | /*****************************************************************************************/ 96 | // uninitialized_fill 97 | // 在 [first, last) 区间内填充元素值 98 | /*****************************************************************************************/ 99 | template 100 | void 101 | unchecked_uninit_fill(ForwardIter first, ForwardIter last, const T& value, std::true_type) 102 | { 103 | mystl::fill(first, last, value); 104 | } 105 | 106 | template 107 | void 108 | unchecked_uninit_fill(ForwardIter first, ForwardIter last, const T& value, std::false_type) 109 | { 110 | auto cur = first; 111 | try 112 | { 113 | for (; cur != last; ++cur) 114 | { 115 | mystl::construct(&*cur, value); 116 | } 117 | } 118 | catch (...) 119 | { 120 | for (;first != cur; ++first) 121 | mystl::destroy(&*first); 122 | } 123 | } 124 | 125 | template 126 | void uninitialized_fill(ForwardIter first, ForwardIter last, const T& value) 127 | { 128 | mystl::unchecked_uninit_fill(first, last, value, 129 | std::is_trivially_copy_assignable< 130 | typename iterator_traits:: 131 | value_type>{}); 132 | } 133 | 134 | /*****************************************************************************************/ 135 | // uninitialized_fill_n 136 | // 从 first 位置开始,填充 n 个元素值,返回填充结束的位置 137 | /*****************************************************************************************/ 138 | template 139 | ForwardIter 140 | unchecked_uninit_fill_n(ForwardIter first, Size n, const T& value, std::true_type) 141 | { 142 | return mystl::fill_n(first, n, value); 143 | } 144 | 145 | template 146 | ForwardIter 147 | unchecked_uninit_fill_n(ForwardIter first, Size n, const T& value, std::false_type) 148 | { 149 | auto cur = first; 150 | try 151 | { 152 | for (; n > 0; --n, ++cur) 153 | { 154 | mystl::construct(&*cur, value); 155 | } 156 | } 157 | catch (...) 158 | { 159 | for (; first != cur; ++first) 160 | mystl::destroy(&*first); 161 | } 162 | return cur; 163 | } 164 | 165 | template 166 | ForwardIter uninitialized_fill_n(ForwardIter first, Size n, const T& value) 167 | { 168 | return mystl::unchecked_uninit_fill_n(first, n, value, 169 | std::is_trivially_copy_assignable< 170 | typename iterator_traits:: 171 | value_type>{}); 172 | } 173 | 174 | /*****************************************************************************************/ 175 | // uninitialized_move 176 | // 把[first, last)上的内容移动到以 result 为起始处的空间,返回移动结束的位置 177 | /*****************************************************************************************/ 178 | template 179 | ForwardIter 180 | unchecked_uninit_move(InputIter first, InputIter last, ForwardIter result, std::true_type) 181 | { 182 | return mystl::move(first, last, result); 183 | } 184 | 185 | template 186 | ForwardIter 187 | unchecked_uninit_move(InputIter first, InputIter last, ForwardIter result, std::false_type) 188 | { 189 | ForwardIter cur = result; 190 | try 191 | { 192 | for (; first != last; ++first, ++cur) 193 | { 194 | mystl::construct(&*cur, mystl::move(*first)); 195 | } 196 | } 197 | catch (...) 198 | { 199 | mystl::destroy(result, cur); 200 | } 201 | return cur; 202 | } 203 | 204 | template 205 | ForwardIter uninitialized_move(InputIter first, InputIter last, ForwardIter result) 206 | { 207 | return mystl::unchecked_uninit_move(first, last, result, 208 | std::is_trivially_move_assignable< 209 | typename iterator_traits:: 210 | value_type>{}); 211 | } 212 | 213 | /*****************************************************************************************/ 214 | // uninitialized_move_n 215 | // 把[first, first + n)上的内容移动到以 result 为起始处的空间,返回移动结束的位置 216 | /*****************************************************************************************/ 217 | template 218 | ForwardIter 219 | unchecked_uninit_move_n(InputIter first, Size n, ForwardIter result, std::true_type) 220 | { 221 | return mystl::move(first, first + n, result); 222 | } 223 | 224 | template 225 | ForwardIter 226 | unchecked_uninit_move_n(InputIter first, Size n, ForwardIter result, std::false_type) 227 | { 228 | auto cur = result; 229 | try 230 | { 231 | for (; n > 0; --n, ++first, ++cur) 232 | { 233 | mystl::construct(&*cur, mystl::move(*first)); 234 | } 235 | } 236 | catch (...) 237 | { 238 | for (; result != cur; ++result) 239 | mystl::destroy(&*result); 240 | throw; 241 | } 242 | return cur; 243 | } 244 | 245 | template 246 | ForwardIter uninitialized_move_n(InputIter first, Size n, ForwardIter result) 247 | { 248 | return mystl::unchecked_uninit_move_n(first, n, result, 249 | std::is_trivially_move_assignable< 250 | typename iterator_traits:: 251 | value_type>{}); 252 | } 253 | 254 | } // namespace mystl 255 | #endif // !MYTINYSTL_UNINITIALIZED_H_ 256 | 257 | -------------------------------------------------------------------------------- /MyTinySTL/util.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_UTIL_H_ 2 | #define MYTINYSTL_UTIL_H_ 3 | 4 | // 这个文件包含一些通用工具,包括 move, forward, swap 等函数,以及 pair 等 5 | 6 | #include 7 | 8 | #include "type_traits.h" 9 | 10 | namespace mystl 11 | { 12 | 13 | // move 14 | 15 | template 16 | typename std::remove_reference::type&& move(T&& arg) noexcept 17 | { 18 | return static_cast::type&&>(arg); 19 | } 20 | 21 | // forward 22 | 23 | template 24 | T&& forward(typename std::remove_reference::type& arg) noexcept 25 | { 26 | return static_cast(arg); 27 | } 28 | 29 | template 30 | T&& forward(typename std::remove_reference::type&& arg) noexcept 31 | { 32 | static_assert(!std::is_lvalue_reference::value, "bad forward"); 33 | return static_cast(arg); 34 | } 35 | 36 | // swap 37 | 38 | template 39 | void swap(Tp& lhs, Tp& rhs) 40 | { 41 | auto tmp(mystl::move(lhs)); 42 | lhs = mystl::move(rhs); 43 | rhs = mystl::move(tmp); 44 | } 45 | 46 | template 47 | ForwardIter2 swap_range(ForwardIter1 first1, ForwardIter1 last1, ForwardIter2 first2) 48 | { 49 | for (; first1 != last1; ++first1, (void) ++first2) 50 | mystl::swap(*first1, *first2); 51 | return first2; 52 | } 53 | 54 | template 55 | void swap(Tp(&a)[N], Tp(&b)[N]) 56 | { 57 | mystl::swap_range(a, a + N, b); 58 | } 59 | 60 | // -------------------------------------------------------------------------------------- 61 | // pair 62 | 63 | // 结构体模板 : pair 64 | // 两个模板参数分别表示两个数据的类型 65 | // 用 first 和 second 来分别取出第一个数据和第二个数据 66 | template 67 | struct pair 68 | { 69 | typedef Ty1 first_type; 70 | typedef Ty2 second_type; 71 | 72 | first_type first; // 保存第一个数据 73 | second_type second; // 保存第二个数据 74 | 75 | // default constructiable 76 | template ::value && 79 | std::is_default_constructible::value, void>::type> 80 | constexpr pair() 81 | : first(), second() 82 | { 83 | } 84 | 85 | // implicit constructiable for this type 86 | template ::value && 89 | std::is_copy_constructible::value && 90 | std::is_convertible::value && 91 | std::is_convertible::value, int>::type = 0> 92 | constexpr pair(const Ty1& a, const Ty2& b) 93 | : first(a), second(b) 94 | { 95 | } 96 | 97 | // explicit constructible for this type 98 | template ::value && 101 | std::is_copy_constructible::value && 102 | (!std::is_convertible::value || 103 | !std::is_convertible::value), int>::type = 0> 104 | explicit constexpr pair(const Ty1& a, const Ty2& b) 105 | : first(a), second(b) 106 | { 107 | } 108 | 109 | pair(const pair& rhs) = default; 110 | pair(pair&& rhs) = default; 111 | 112 | // implicit constructiable for other type 113 | template ::value && 116 | std::is_constructible::value && 117 | std::is_convertible::value && 118 | std::is_convertible::value, int>::type = 0> 119 | constexpr pair(Other1&& a, Other2&& b) 120 | : first(mystl::forward(a)), 121 | second(mystl::forward(b)) 122 | { 123 | } 124 | 125 | // explicit constructiable for other type 126 | template ::value && 129 | std::is_constructible::value && 130 | (!std::is_convertible::value || 131 | !std::is_convertible::value), int>::type = 0> 132 | explicit constexpr pair(Other1&& a, Other2&& b) 133 | : first(mystl::forward(a)), 134 | second(mystl::forward(b)) 135 | { 136 | } 137 | 138 | // implicit constructiable for other pair 139 | template ::value && 142 | std::is_constructible::value && 143 | std::is_convertible::value && 144 | std::is_convertible::value, int>::type = 0> 145 | constexpr pair(const pair& other) 146 | : first(other.first), 147 | second(other.second) 148 | { 149 | } 150 | 151 | // explicit constructiable for other pair 152 | template ::value && 155 | std::is_constructible::value && 156 | (!std::is_convertible::value || 157 | !std::is_convertible::value), int>::type = 0> 158 | explicit constexpr pair(const pair& other) 159 | : first(other.first), 160 | second(other.second) 161 | { 162 | } 163 | 164 | // implicit constructiable for other pair 165 | template ::value && 168 | std::is_constructible::value && 169 | std::is_convertible::value && 170 | std::is_convertible::value, int>::type = 0> 171 | constexpr pair(pair&& other) 172 | : first(mystl::forward(other.first)), 173 | second(mystl::forward(other.second)) 174 | { 175 | } 176 | 177 | // explicit constructiable for other pair 178 | template ::value && 181 | std::is_constructible::value && 182 | (!std::is_convertible::value || 183 | !std::is_convertible::value), int>::type = 0> 184 | explicit constexpr pair(pair&& other) 185 | : first(mystl::forward(other.first)), 186 | second(mystl::forward(other.second)) 187 | { 188 | } 189 | 190 | // copy assign for this pair 191 | pair& operator=(const pair& rhs) 192 | { 193 | if (this != &rhs) 194 | { 195 | first = rhs.first; 196 | second = rhs.second; 197 | } 198 | return *this; 199 | } 200 | 201 | // move assign for this pair 202 | pair& operator=(pair&& rhs) 203 | { 204 | if (this != &rhs) 205 | { 206 | first = mystl::move(rhs.first); 207 | second = mystl::move(rhs.second); 208 | } 209 | return *this; 210 | } 211 | 212 | // copy assign for other pair 213 | template 214 | pair& operator=(const pair& other) 215 | { 216 | first = other.first; 217 | second = other.second; 218 | return *this; 219 | } 220 | 221 | // move assign for other pair 222 | template 223 | pair& operator=(pair&& other) 224 | { 225 | first = mystl::forward(other.first); 226 | second = mystl::forward(other.second); 227 | return *this; 228 | } 229 | 230 | ~pair() = default; 231 | 232 | void swap(pair& other) 233 | { 234 | if (this != &other) 235 | { 236 | mystl::swap(first, other.first); 237 | mystl::swap(second, other.second); 238 | } 239 | } 240 | 241 | }; 242 | 243 | // 重载比较操作符 244 | template 245 | bool operator==(const pair& lhs, const pair& rhs) 246 | { 247 | return lhs.first == rhs.first && lhs.second == rhs.second; 248 | } 249 | 250 | template 251 | bool operator<(const pair& lhs, const pair& rhs) 252 | { 253 | return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); 254 | } 255 | 256 | template 257 | bool operator!=(const pair& lhs, const pair& rhs) 258 | { 259 | return !(lhs == rhs); 260 | } 261 | 262 | template 263 | bool operator>(const pair& lhs, const pair& rhs) 264 | { 265 | return rhs < lhs; 266 | } 267 | 268 | template 269 | bool operator<=(const pair& lhs, const pair& rhs) 270 | { 271 | return !(rhs < lhs); 272 | } 273 | 274 | template 275 | bool operator>=(const pair& lhs, const pair& rhs) 276 | { 277 | return !(lhs < rhs); 278 | } 279 | 280 | // 重载 mystl 的 swap 281 | template 282 | void swap(pair& lhs, pair& rhs) 283 | { 284 | lhs.swap(rhs); 285 | } 286 | 287 | // 全局函数,让两个数据成为一个 pair 288 | template 289 | pair make_pair(Ty1&& first, Ty2&& second) 290 | { 291 | return pair(mystl::forward(first), mystl::forward(second)); 292 | } 293 | 294 | } 295 | 296 | #endif // !MYTINYSTL_UTIL_H_ 297 | 298 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MyTinySTL 2 | ===== 3 | [![Build Status](https://travis-ci.org/Alinshans/MyTinySTL.svg?branch=master)](https://travis-ci.org/Alinshans/MyTinySTL) [![Build Status](https://ci.appveyor.com/api/projects/status/github/Alinshans/MyTinySTL?branch=master&svg=true)](https://ci.appveyor.com/project/Alinshans/mytinystl) [![Release](https://img.shields.io/github/release/Alinshans/MyTinySTL.svg)](https://github.com/Alinshans/MyTinySTL/releases) [![License](https://img.shields.io/badge/License-MIT%20License-blue.svg)](https://opensource.org/licenses/MIT) [![Chat](https://img.shields.io/badge/chat-on%20gitter-FF6EB4.svg)](https://gitter.im/alinshans/MyTinySTL) 4 | 5 | ## 简介 6 | 基于 `C++11` 的 `tinySTL`,这是我的第一个项目,使用了中文文档与中文注释,有不规范或不当的地方还请海涵。刚开始是作为新手练习用途,直到现在已经发布了 `2.x.x` 版本。实现了大部分 STL 中的容器与函数,但仍存在许多不足与 bug 。从 `2.x.x` 版本开始,本项目会进入长期维护的阶段,即基本不会增加新的内容,只修复发现的 bug。如发现错误,还请在 [`Issues`](https://github.com/Alinshans/MyTinySTL/issues) 中指出,欢迎 `Fork` 和 [`Pull requests`](https://github.com/Alinshans/MyTinySTL/pulls) 改善代码,谢谢! 7 | 8 | ## 支持 9 | 10 | * 操作系统 11 | * linux 12 | * windows 13 | * osx 14 | * 编译器 15 | * g++ 5.4 或以上 16 | * clang++ 3.5 或以上 17 | * msvc 14.0 或以上 18 | 19 | ## 需要 20 | * 使用 cmake 2.8 来构建项目(**可选**) 21 | 22 | ## 运行 23 | 24 | 如果你想要运行测试,请先阅读 [这个](https://github.com/Alinshans/MyTinySTL/blob/master/Test/README.md) 。 25 | 26 | * gcc/clang on linux/osx 27 | 1. 克隆仓库 28 | ```bash 29 | $ git clone git@github.com:Alinshans/MyTinySTL.git 30 | $ cd MyTinySTL 31 | ``` 32 | 2. 构建并运行 33 | ```bash 34 | $ mkdir build && cd build 35 | $ cmake .. 36 | $ make 37 | $ cd ../bin && ./stltest 38 | ``` 39 | 40 | * msvc on windows 41 | 1. 克隆仓库或 [Download ZIP](https://github.com/Alinshans/MyTinySTL/archive/master.zip) 42 | 2. 使用 `vs2015`(或 `vs2017`)打开 `MSVC/MyTinySTL_VS2015.sln`,配置成 `Release` 模式,(Ctrl + F5)开始执行。 43 | 44 | ## 文档 45 | 见 [Wiki](https://github.com/Alinshans/MyTinySTL/wiki)。 46 | 47 | ## 测试 48 | 见 [Test](https://github.com/Alinshans/MyTinySTL/tree/master/Test)。 49 | 50 | --- 51 | 52 | ## Introduction 53 | 54 | This is a `tinySTL` based on `C++11`, which is my first project for practice. I use the Chinese documents and annotations for convenience, maybe there will be an English version later, but now I have no time to do that yet. Now I have released version `2.0.0`. I have achieved the vast majority of the containers and functions of `STL`, and there may be some deficiencies and bugs. From the version `2.x.x`, the project will enter the stage of long-term maintenance, i.e., I probably will not add new content but only fix bugs found. If you find any bugs, please point out that in [`Issues`](https://github.com/Alinshans/MyTinySTL/issues), or make a [`Pull requests`](https://github.com/Alinshans/MyTinySTL/pulls) to improve it, thanks! 55 | 56 | ## Supported 57 | 58 | * os 59 | * linux 60 | * windows 61 | * osx 62 | * complier 63 | * g++ 5.4 or later 64 | * clang++ 3.5 or later 65 | * msvc 14.0 or later 66 | 67 | ## Required 68 | 69 | * Use cmake 2.8 to build this project (**Optional**) 70 | 71 | ## Run test 72 | 73 | If you want to run the test, please read [this](https://github.com/Alinshans/MyTinySTL/blob/master/Test/README.md) first. 74 | 75 | * gcc/clang on linux/osx 76 | 77 | 1. git clone 78 | ```bash 79 | $ git clone git@github.com:Alinshans/MyTinySTL.git 80 | $ cd MyTinySTL 81 | ``` 82 | 2. build and run 83 | ```bash 84 | $ mkdir build && cd build 85 | $ cmake .. 86 | $ make 87 | $ cd ../bin && ./stltest 88 | ``` 89 | 90 | * msvc on windows 91 | 92 | 1. git clone or [Download ZIP](https://github.com/Alinshans/MyTinySTL/archive/master.zip) 93 | 2. use `vs2015`(or `vs2017`) open the file `MSVC/MyTinySTL_VS2015.sln`, configured in `Release`, run this project(Ctrl + F5). 94 | 95 | ## Documents 96 | 97 | See [Wiki](https://github.com/Alinshans/MyTinySTL/wiki). 98 | 99 | ## Test 100 | 101 | See [Test](https://github.com/Alinshans/MyTinySTL/tree/master/Test). 102 | -------------------------------------------------------------------------------- /Test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/MyTinySTL) 2 | set(APP_SRC test.cpp) 3 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 4 | add_executable(stltest ${APP_SRC}) -------------------------------------------------------------------------------- /Test/Lib/redbud/io/color.h: -------------------------------------------------------------------------------- 1 | // ============================================================================ 2 | // Copyright (c) 2017 Alinshans. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE for details. 4 | // 5 | // Header File : redbud/io/color.h 6 | // 7 | // This file is used to control font format and color in the terminal, which 8 | // refers to a project on github, see https://github.com/agauniyal/rang . 9 | // ============================================================================ 10 | 11 | #ifndef ALINSHANS_REDBUD_IO_COLOR_H_ 12 | #define ALINSHANS_REDBUD_IO_COLOR_H_ 13 | 14 | #include "../platform.h" 15 | 16 | #if defined(REDBUD_LINUX) || defined(REDBUD_OSX) 17 | #include // getenv 18 | #include // strstr 19 | #elif defined(REDBUD_WIN) 20 | #include 21 | #include 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace redbud 29 | { 30 | namespace io 31 | { 32 | 33 | // ============================================================================ 34 | // Enumerates the ANSI escape code corresponding to the font attributes. 35 | // See https://en.wikipedia.org/wiki/ANSI_escape_code for details. 36 | // 37 | // Example: 38 | // using namespace redbud::io; 39 | // std::cout << fg::red << "This text has a red foreground color\n"; 40 | // std::cout << bg::green << "This text has a green background color\n" 41 | // ============================================================================ 42 | 43 | // Sets the text format, some of them is not widely supported. 44 | enum class format 45 | { 46 | reset = 0, // All attributes off. 47 | bold = 1, // Bold or increased intensity. 48 | faint = 2, // Faint (decreased intensity). 49 | italic = 3, // Italian font. 50 | underline = 4, // Underline. 51 | blinkslow = 5, // Blink slowly. 52 | blinkrapid = 6, // Blink quickly. 53 | inverse = 7, // Swap foreground and background. 54 | conceal = 8, // Hide the text. 55 | strikeline = 9 // Characters legible, but marked for deletion. 56 | }; 57 | 58 | // Sets the foreground color. 59 | enum class fg 60 | { 61 | black = 30, 62 | red = 31, 63 | green = 32, 64 | yellow = 33, 65 | blue = 34, 66 | purple = 35, 67 | cyan = 36, 68 | white = 37, 69 | reserve = 38, 70 | reset = 39 71 | }; 72 | 73 | // Sets the background color. 74 | enum class bg 75 | { 76 | black = 40, 77 | red = 41, 78 | green = 42, 79 | yellow = 43, 80 | blue = 44, 81 | purple = 45, 82 | cyan = 46, 83 | white = 47, 84 | reserve = 38, 85 | reset = 39 86 | }; 87 | 88 | // Sets the highlight foreground color. 89 | enum class hfg 90 | { 91 | black = 90, 92 | red = 91, 93 | green = 92, 94 | yellow = 93, 95 | blue = 94, 96 | purple = 95, 97 | cyan = 96, 98 | white = 97 99 | }; 100 | 101 | // Sets the highlight background color. 102 | enum class hbg 103 | { 104 | black = 100, 105 | red = 101, 106 | green = 102, 107 | yellow = 103, 108 | blue = 104, 109 | purple = 105, 110 | cyan = 106, 111 | white = 107 112 | }; 113 | 114 | // Sets the control state. 115 | enum class state 116 | { 117 | automatic = 0, // Automatic control. 118 | manual = 1 // Manual control. 119 | }; 120 | 121 | // ---------------------------------------------------------------------------- 122 | // Details 123 | namespace details 124 | { 125 | 126 | // Manages associated stream buffer. 127 | inline const std::streambuf*& get_coutbuf() 128 | { 129 | static const std::streambuf* pout = std::cout.rdbuf(); 130 | return pout; 131 | } 132 | 133 | inline const std::streambuf*& get_cerrbuf() 134 | { 135 | static const std::streambuf* perr = std::cerr.rdbuf(); 136 | return perr; 137 | } 138 | 139 | inline const std::streambuf*& get_clogbuf() 140 | { 141 | static const std::streambuf* plog = std::clog.rdbuf(); 142 | return plog; 143 | } 144 | 145 | // Gets an unique integer to use as index to iword() 146 | inline int get_iword() 147 | { 148 | static int i = std::ios_base::xalloc(); 149 | return i; 150 | } 151 | 152 | // Determines whether the terminal color of this system can be modified. 153 | inline bool is_modifiable() 154 | { 155 | #if defined(REDBUD_LINUX) || defined(REDBUD_OSX) 156 | static constexpr const char* terms[] = { 157 | "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", 158 | "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm" 159 | }; 160 | const char *penv = std::getenv("TERM"); 161 | if (penv == nullptr) 162 | { 163 | return false; 164 | } 165 | bool result = false; 166 | for (const auto& t : terms) 167 | { 168 | if (std::strstr(penv, t) != nullptr) 169 | { 170 | result = true; 171 | break; 172 | } 173 | } 174 | 175 | #elif defined(REDBUD_WIN) 176 | static constexpr bool result = true; 177 | #endif 178 | return result; 179 | } 180 | 181 | /// Determines whether the buffer stream reaches the end. 182 | inline bool is_terminal(const std::streambuf* buf) 183 | { 184 | if (buf == get_coutbuf()) 185 | { 186 | #if defined(REDBUD_LINUX) || defined(REDBUD_OSX) 187 | return isatty(fileno(stdout)) ? true : false; 188 | #elif defined(REDBUD_WIN) 189 | return _isatty(_fileno(stdout)) ? true : false; 190 | #endif 191 | } 192 | 193 | if (buf == get_cerrbuf() || buf == get_clogbuf()) 194 | { 195 | #if defined(REDBUD_LINUX) || defined(REDBUD_OSX) 196 | return isatty(fileno(stderr)) ? true : false; 197 | #elif defined(REDBUD_WIN) 198 | return _isatty(_fileno(stderr)) ? true : false; 199 | #endif 200 | } 201 | return false; 202 | } 203 | 204 | // For overloading standard output stream. 205 | template 206 | using color_return_t = typename std::enable_if< 207 | std::is_same::value || 208 | std::is_same::value || 209 | std::is_same::value || 210 | std::is_same::value || 211 | std::is_same::value, 212 | std::ostream&>::type; 213 | 214 | template 215 | using state_return_t = typename std::enable_if< 216 | std::is_same::value, 217 | std::ostream&>::type; 218 | 219 | // Sets the format and color of the text. 220 | #if defined(REDBUD_LINUX) || defined(REDBUD_OSX) 221 | template 222 | inline color_return_t set_color(std::ostream& os, const T& value) 223 | { 224 | return os << "\033[" << static_cast(value) << "m"; 225 | } 226 | 227 | #elif defined(REDBUD_WIN) 228 | 229 | static constexpr WORD default_state = (FOREGROUND_BLUE | 230 | FOREGROUND_GREEN | 231 | FOREGROUND_RED); 232 | 233 | // Gets the corresponding RGB value on Windows. 234 | inline WORD get_rgb(WORD rgb) 235 | { 236 | static constexpr WORD cor[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 237 | return cor[rgb]; 238 | } 239 | 240 | // Sets font attributes on Windows. 241 | inline void set_attributes(redbud::io::fg color, WORD& state) 242 | { 243 | if (color == redbud::io::fg::reserve) 244 | { 245 | return; 246 | } 247 | state &= 0xFFF0; 248 | if (color == redbud::io::fg::reset) 249 | { 250 | state |= default_state; 251 | return; 252 | } 253 | state |= get_rgb(static_cast(color) - 30); 254 | } 255 | 256 | inline void set_attributes(redbud::io::bg color, WORD& state) 257 | { 258 | if (color == redbud::io::bg::reserve) 259 | { 260 | return; 261 | } 262 | state &= 0xFF0F; 263 | if (color == redbud::io::bg::reset) 264 | { 265 | return; 266 | } 267 | state |= get_rgb(static_cast(color) - 40) << 4; 268 | } 269 | 270 | inline void set_attributes(redbud::io::hfg color, WORD& state) 271 | { 272 | state &= 0xFFF0; 273 | state |= (static_cast(0x8) | 274 | get_rgb(static_cast(color) - 90)); 275 | } 276 | 277 | inline void set_attributes(redbud::io::hbg color, WORD& state) 278 | { 279 | state &= 0xFF0F; 280 | state |= (static_cast(0x80) | 281 | get_rgb(static_cast(color) - 100) << 4); 282 | } 283 | 284 | inline void set_attributes(redbud::io::format format, WORD& state) 285 | { 286 | if (format == redbud::io::format::reset) 287 | { 288 | state = default_state; 289 | } 290 | } 291 | 292 | inline WORD& current_state() 293 | { 294 | static WORD state = default_state; 295 | return state; 296 | } 297 | 298 | inline HANDLE get_console_handle() 299 | { 300 | static HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); 301 | return h; 302 | } 303 | 304 | template 305 | inline color_return_t set_color(std::ostream& os, const T& value) 306 | { 307 | HANDLE h = get_console_handle(); 308 | if (h && is_terminal(os.rdbuf())) 309 | { 310 | set_attributes(value, current_state()); 311 | SetConsoleTextAttribute(h, current_state()); 312 | return os; 313 | } 314 | return os; 315 | } 316 | #endif 317 | 318 | } // namespace details 319 | 320 | // ---------------------------------------------------------------------------- 321 | // Overloads standard output stream to control the color of text. 322 | 323 | template 324 | inline details::color_return_t 325 | operator<<(std::ostream& os, const T& value) 326 | { 327 | return (os.iword(details::get_iword()) || 328 | (details::is_modifiable() && 329 | details::is_terminal(os.rdbuf()))) 330 | ? details::set_color(os, value) 331 | : os; 332 | } 333 | 334 | template 335 | inline details::state_return_t 336 | operator<<(std::ostream& os, const T& value) 337 | { 338 | if (value == redbud::io::state::automatic) 339 | { 340 | os.iword(details::get_iword()) = 0; 341 | } 342 | else if (value == redbud::io::state::manual) 343 | { 344 | os.iword(details::get_iword()) = 1; 345 | } 346 | return os; 347 | } 348 | 349 | } // namespace io 350 | } // namespace redbud 351 | #endif // !ALINSHANS_REDBUD_IO_COLOR_H_ 352 | -------------------------------------------------------------------------------- /Test/Lib/redbud/platform.h: -------------------------------------------------------------------------------- 1 | // ============================================================================ 2 | // Copyright (c) 2017 Alinshans. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE for details. 4 | // 5 | // Header File : redbud/platform.h 6 | // 7 | // This file contains some preprocessing macros related to the platform. 8 | // ============================================================================ 9 | 10 | #ifndef ALINSHANS_REDBUD_PLATFORM_H_ 11 | #define ALINSHANS_REDBUD_PLATFORM_H_ 12 | 13 | // ---------------------------------------------------------------------------- 14 | // os 15 | 16 | #if defined(WIN32) || defined(_WIN32) || defined(_WIN64) 17 | #define REDBUD_WIN 1 18 | #elif defined(__unix__) || defined(__unix) || defined(__linux__) 19 | #define REDBUD_LINUX 1 20 | #elif defined(__APPLE__) || defined(__MACH__) 21 | #define REDBUD_OSX 1 22 | #else 23 | #error "System that is not supported yet." 24 | #endif 25 | 26 | // ---------------------------------------------------------------------------- 27 | // complier 28 | 29 | #if defined(__clang__) 30 | #define REDBUD_CLANG __clang__ 31 | #elif defined(__GNUC__) 32 | #define REDBUD_GNUC __GNUC__ 33 | #elif defined(_MSC_VER) 34 | #define REDBUD_MSVC _MSC_VER 35 | #else 36 | #error "Complier that is not supported yet." 37 | #endif 38 | 39 | // ---------------------------------------------------------------------------- 40 | // stringify 41 | 42 | #define REDBUD_TO_STRING(x) #x 43 | #define REDBUD_STRING(x) REDBUD_TO_STRING(x) 44 | 45 | // ---------------------------------------------------------------------------- 46 | // join 47 | 48 | #define REDBUD_DO_JOIN(x ,y) x##y 49 | #define REDBUD_JOIN(x, y) REDBUD_DO_JOIN(x, y) 50 | 51 | // ---------------------------------------------------------------------------- 52 | // version 53 | 54 | #define REDBUD_MAJOR 1 55 | #define REDBUD_MINOR 0 56 | #define REDBUD_PATCH 0 57 | #define REDBUD_VERSION \ 58 | REDBUD_STRING(REDBUD_MAJOR.REDBUD_MINOR.REDBUD_PATCH) 59 | 60 | #define _VERSION_CODE(x,y,z) \ 61 | (((x)*100000) + ((y)*100) + (z)) 62 | 63 | #define GNUC_VERSION \ 64 | _VERSION_CODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 65 | 66 | #define CLANG_VERSION \ 67 | _VERSION_CODE(__clang_major__, __clang_minor__, __clang_patchlevel__) 68 | 69 | // ---------------------------------------------------------------------------- 70 | // redbud API 71 | 72 | #ifndef _REDBUD_API 73 | #define _REDBUD_API ::redbud:: 74 | #endif 75 | 76 | // ---------------------------------------------------------------------------- 77 | // C++11 required 78 | 79 | #ifndef REDBUD_HAS_CXX11 80 | #if defined(REDBUD_MSVC) && (REDBUD_MSVC >= 1900) 81 | #define REDBUD_HAS_CXX11 1 82 | #elif defined(REDBUD_GNUC) && (GNUC_VERSION >= _VERSION_CODE(4,8,0)) && \ 83 | defined(__GXX_EXPERIMENTAL_CXX0X__) 84 | #define REDBUD_HAS_CXX11 1 85 | #elif defined(REDBUD_CLANG) && (CLANG_VERSION >= _VERSION_CODE(3,3,0)) 86 | #define REDBUD_HAS_CXX11 1 87 | #else 88 | #define REDBUD_HAS_CXX11 0 89 | #endif 90 | #endif // !REDBUD_HAS_CXX11 91 | 92 | #if REDBUD_HAS_CXX11 == 0 93 | #error "C++11 required." 94 | #endif 95 | 96 | // ---------------------------------------------------------------------------- 97 | // Undefines macro min and max in MSVC. 98 | 99 | namespace redbud 100 | { 101 | 102 | #if REDBUD_MSVC 103 | #define NOMINMAX 104 | #endif 105 | 106 | } 107 | 108 | #endif // !ALINSHANS_REDBUD_PLATFORM_H_ 109 | -------------------------------------------------------------------------------- /Test/README.md: -------------------------------------------------------------------------------- 1 | 单元测试 (Unit test) 2 | ===== 3 | ## 测试环境 (Test environment) 4 | 测试直接在 `Travis CI` 和 `AppVeyor` 上构建并运行,已在以下环境中做过测试: 5 | 6 | Tests were built and run directly on `Tracis CI` and `AppVeyor` and had been tested in the following environments: 7 | 8 | * linux, ubuntu 14.04, gcc5/6/7 9 | * osx, xcode5/6/7/8 10 | * windows, VS2015/VS2017, [x64|x86], [Release|Debug] 11 | 12 | ## 测试框架 (Test frame) 13 | 在 [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h) 中,用了两个类实现了一个简单的测试框架,并定义了大量宏来封装测试过程。
14 | In this file [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h), I used two class to implement a simple test framework, and defined a lot of macros to package testing process. 15 | 16 | ## 测试内容 (Test content) 17 | 在 [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h) 中定义了两个宏,`PERFORMANCE_TEST_ON` 和 `LARGER_TEST_DATA_ON`。`PERFORMANCE_TEST_ON` 代表开启性能测试,默认定义为 `1`。`LARGER_TEST_DATA_ON` 代表增大测试数据,默认定义为 `0`。**如果你想把 `LARGER_TEST_DATA_ON` 设置为 `1`,建议电脑配置为:处理器 i5 或以上,内存 8G 以上。**
18 | In this file [test.h](https://github.com/Alinshans/MyTinySTL/blob/master/Test/test.h), I defined two marcos: `PERFORMANCE_TEST_ON` and `LARGER_TEST_DATA_ON`. `PERFORMANCE_TEST_ON` means to run performance test, the default is defined as `1`. `LARGER_TEST_DATA_ON` means to increase the test data, the default is defined as `0`. **If you want to set `LARGER_TEST_DATA_ON` to `1`, the proposed computer configuration is: CPU i5 or above, memory 8G or more.** 19 | 20 | 测试案例如下:
21 | The test cases are as follows: 22 | 23 | * [algorithm](https://github.com/Alinshans/MyTinySTL/blob/master/Test/algorithm_test.h) *(100%/100%)* 24 | * [algorithm_performance](https://github.com/Alinshans/MyTinySTL/blob/master/Test/algorithm_performance_test.h) *(100%/100%)* 25 | * [deque](https://github.com/Alinshans/MyTinySTL/blob/master/Test/deque_test.h) *(100%/100%)* 26 | * [list](https://github.com/Alinshans/MyTinySTL/blob/master/Test/list_test.h) *(100%/100%)* 27 | * [map](https://github.com/Alinshans/MyTinySTL/blob/master/Test/map_test.h) *(100%/100%)* 28 | * map 29 | * multimap 30 | * [queue](https://github.com/Alinshans/MyTinySTL/blob/master/Test/queue_test.h) *(100%/100%)* 31 | * queue 32 | * priority_queue 33 | * [set](https://github.com/Alinshans/MyTinySTL/blob/master/Test/set_test.h) *(100%/100%)* 34 | * set 35 | * multiset 36 | * [stack](https://github.com/Alinshans/MyTinySTL/blob/master/Test/stack_test.h) *(100%/100%)* 37 | * [string_test](https://github.com/Alinshans/MyTinySTL/blob/master/Test/string_test.h) *(100%/100%)* 38 | * [unordered_map](https://github.com/Alinshans/MyTinySTL/blob/master/Test/unordered_map_test.h) *(100%/100%)* 39 | * unordered_map 40 | * unordered_multimap 41 | * [unordered_set](https://github.com/Alinshans/MyTinySTL/blob/master/Test/unordered_set_test.h) *(100%/100%)* 42 | * unordered_set 43 | * unordered_multiset 44 | * [vector](https://github.com/Alinshans/MyTinySTL/blob/master/Test/vector_test.h) *(100%/100%)* 45 | 46 | 47 | ## 测试结果 (Test result) 48 | 见 [Travis CI](https://travis-ci.org/Alinshans/MyTinySTL) 和 [AppVeyor](https://ci.appveyor.com/project/Alinshans/mytinystl)。 49 | 50 | See [Travis CI](https://travis-ci.org/Alinshans/MyTinySTL) and [AppVeyor](https://ci.appveyor.com/project/Alinshans/mytinystl). 51 | 52 | -------------------------------------------------------------------------------- /Test/algorithm_performance_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ 2 | #define MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ 3 | 4 | // 仅仅针对 sort, binary_search 做了性能测试 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/algorithm.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace algorithm_performance_test 16 | { 17 | 18 | // 函数性能测试宏定义 19 | #define FUN_TEST1(mode, fun, count) do { \ 20 | std::string fun_name = #fun; \ 21 | srand((int)time(0)); \ 22 | char buf[10]; \ 23 | clock_t start, end; \ 24 | int *arr = new int[count]; \ 25 | for(size_t i = 0; i < count; ++i) *(arr + i) = rand(); \ 26 | start = clock(); \ 27 | mode::fun(arr, arr + count); \ 28 | end = clock(); \ 29 | int n = static_cast(static_cast(end - start) \ 30 | / CLOCKS_PER_SEC * 1000); \ 31 | std::snprintf(buf, sizeof(buf), "%d", n); \ 32 | std::string t = buf; \ 33 | t += "ms |"; \ 34 | std::cout << std::setw(WIDE) << t; \ 35 | delete []arr; \ 36 | } while(0) 37 | 38 | #define FUN_TEST2(mode, fun, count) do { \ 39 | std::string fun_name = #fun; \ 40 | srand((int)time(0)); \ 41 | char buf[10]; \ 42 | clock_t start, end; \ 43 | int *arr = new int[count]; \ 44 | for(size_t i = 0; i < count; ++i) *(arr + i) = rand(); \ 45 | start = clock(); \ 46 | for(size_t i = 0; i < count; ++i) \ 47 | mode::fun(arr, arr + count, rand()); \ 48 | end = clock(); \ 49 | int n = static_cast(static_cast(end - start) \ 50 | / CLOCKS_PER_SEC * 1000); \ 51 | std::snprintf(buf, sizeof(buf), "%d", n); \ 52 | std::string t = buf; \ 53 | t += "ms |"; \ 54 | std::cout << std::setw(WIDE) << t; \ 55 | delete []arr; \ 56 | } while(0) 57 | 58 | void binary_search_test() 59 | { 60 | std::cout << "[------------------- function : binary_search ------------------]" << std::endl; 61 | std::cout << "| orders of magnitude |"; 62 | TEST_LEN(LEN1, LEN2, LEN3, WIDE); 63 | std::cout << "| std |"; 64 | FUN_TEST2(std, binary_search, LEN1); 65 | FUN_TEST2(std, binary_search, LEN2); 66 | FUN_TEST2(std, binary_search, LEN3); 67 | std::cout << std::endl << "| mystl |"; 68 | FUN_TEST2(mystl, binary_search, LEN1); 69 | FUN_TEST2(mystl, binary_search, LEN2); 70 | FUN_TEST2(mystl, binary_search, LEN3); 71 | std::cout << std::endl; 72 | } 73 | 74 | void sort_test() 75 | { 76 | std::cout << "[----------------------- function : sort -----------------------]" << std::endl; 77 | std::cout << "| orders of magnitude |"; 78 | TEST_LEN(LEN1, LEN2, LEN3, WIDE); 79 | std::cout << "| std |"; 80 | FUN_TEST1(std, sort, LEN1); 81 | FUN_TEST1(std, sort, LEN2); 82 | FUN_TEST1(std, sort, LEN3); 83 | std::cout << std::endl << "| mystl |"; 84 | FUN_TEST1(mystl, sort, LEN1); 85 | FUN_TEST1(mystl, sort, LEN2); 86 | FUN_TEST1(mystl, sort, LEN3); 87 | std::cout << std::endl; 88 | } 89 | 90 | void algorithm_performance_test() 91 | { 92 | 93 | #if PERFORMANCE_TEST_ON 94 | std::cout << "[===============================================================]" << std::endl; 95 | std::cout << "[--------------- Run algorithm performance test ----------------]" << std::endl; 96 | sort_test(); 97 | binary_search_test(); 98 | std::cout << "[--------------- End algorithm performance test ----------------]" << std::endl; 99 | std::cout << "[===============================================================]" << std::endl; 100 | #endif // PERFORMANCE_TEST_ON 101 | 102 | } 103 | 104 | } // namespace algorithm_performance_test 105 | } // namespace test 106 | } // namespace mystl 107 | #endif // !MYTINYSTL_ALGORITHM_PERFORMANCE_TEST_H_ 108 | 109 | -------------------------------------------------------------------------------- /Test/deque_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_DEQUE_TEST_H_ 2 | #define MYTINYSTL_DEQUE_TEST_H_ 3 | 4 | // deque test : 测试 deque 的接口和 push_front/push_back 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/deque.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace deque_test 16 | { 17 | 18 | void deque_test() 19 | { 20 | std::cout << "[===============================================================]" << std::endl; 21 | std::cout << "[----------------- Run container test : deque ------------------]" << std::endl; 22 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 23 | int a[] = { 1,2,3,4,5 }; 24 | mystl::deque d1; 25 | mystl::deque d2(5); 26 | mystl::deque d3(5, 1); 27 | mystl::deque d4(a, a + 5); 28 | mystl::deque d5(d2); 29 | mystl::deque d6(std::move(d2)); 30 | mystl::deque d7; 31 | d7 = d3; 32 | mystl::deque d8; 33 | d8 = std::move(d3); 34 | mystl::deque d9{ 1,2,3,4,5,6,7,8,9 }; 35 | mystl::deque d10; 36 | d10 = { 1,2,3,4,5,6,7,8,9 }; 37 | 38 | FUN_AFTER(d1, d1.assign(5, 1)); 39 | FUN_AFTER(d1, d1.assign(8, 8)); 40 | FUN_AFTER(d1, d1.assign(a, a + 5)); 41 | FUN_AFTER(d1, d1.assign({ 1,2,3,4,5 })); 42 | FUN_AFTER(d1, d1.insert(d1.end(), 6)); 43 | FUN_AFTER(d1, d1.insert(d1.end() - 1, 2, 7)); 44 | FUN_AFTER(d1, d1.insert(d1.begin(), a, a + 5)); 45 | FUN_AFTER(d1, d1.erase(d1.begin())); 46 | FUN_AFTER(d1, d1.erase(d1.begin(), d1.begin() + 4)); 47 | FUN_AFTER(d1, d1.emplace_back(8)); 48 | FUN_AFTER(d1, d1.emplace_front(8)); 49 | FUN_AFTER(d1, d1.emplace(d1.begin() + 1, 9)); 50 | FUN_AFTER(d1, d1.push_front(1)); 51 | FUN_AFTER(d1, d1.push_back(2)); 52 | FUN_AFTER(d1, d1.pop_back()); 53 | FUN_AFTER(d1, d1.pop_front()); 54 | FUN_AFTER(d1, d1.shrink_to_fit()); 55 | FUN_AFTER(d1, d1.resize(5)); 56 | FUN_AFTER(d1, d1.resize(8, 8)); 57 | FUN_AFTER(d1, d1.clear()); 58 | FUN_AFTER(d1, d1.shrink_to_fit()); 59 | FUN_AFTER(d1, d1.swap(d4)); 60 | FUN_VALUE(*(d1.begin())); 61 | FUN_VALUE(*(d1.end() - 1)); 62 | FUN_VALUE(*(d1.rbegin())); 63 | FUN_VALUE(*(d1.rend() - 1)); 64 | FUN_VALUE(d1.front()); 65 | FUN_VALUE(d1.back()); 66 | FUN_VALUE(d1.at(1)); 67 | FUN_VALUE(d1[2]); 68 | std::cout << std::boolalpha; 69 | FUN_VALUE(d1.empty()); 70 | std::cout << std::noboolalpha; 71 | FUN_VALUE(d1.size()); 72 | FUN_VALUE(d1.max_size()); 73 | PASSED; 74 | #if PERFORMANCE_TEST_ON 75 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 76 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 77 | std::cout << "| push_front |"; 78 | #if LARGER_TEST_DATA_ON 79 | CON_TEST_P1(deque, push_front, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 80 | #else 81 | CON_TEST_P1(deque, push_front, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 82 | #endif 83 | std::cout << std::endl; 84 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 85 | std::cout << "| push_back |"; 86 | #if LARGER_TEST_DATA_ON 87 | CON_TEST_P1(deque, push_back, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 88 | #else 89 | CON_TEST_P1(deque, push_back, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 90 | #endif 91 | std::cout << std::endl; 92 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 93 | PASSED; 94 | #endif 95 | std::cout << "[----------------- End container test : deque ------------------]" << std::endl; 96 | } 97 | 98 | } // namespace deque_test 99 | } // namespace test 100 | } // namespace mystl 101 | #endif // !MYTINYSTL_DEQUE_TEST_H_ 102 | 103 | -------------------------------------------------------------------------------- /Test/iterator_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_ITERATOR_TEST_H_ 2 | #define MYTINYSTL_ITERATOR_TEST_H_ 3 | 4 | #include "test.h" 5 | #include "../MyTinySTL/iterator.h" 6 | #include "../MyTinySTL/stream_iterator.h" 7 | 8 | namespace mystl 9 | { 10 | namespace test 11 | { 12 | namespace iterator_test 13 | { 14 | 15 | void stream_iterator_test() 16 | { 17 | std::cout << "[===============================================================]\n"; 18 | std::cout << "[------------- Run iterator test : stream_iterator--------------]\n"; 19 | std::cout << "[-------------------------- API test ---------------------------]\n"; 20 | 21 | static_assert(mystl::is_exactly_input_iterator>::value, 22 | "istream_iterator must have input_iterator_tag)"); 23 | 24 | std::istringstream is("1 2 3"); 25 | mystl::istream_iterator first{is}, last; 26 | std::cout << mystl::distance(first, last) << '\n'; 27 | 28 | std::istringstream istream("1 2 3 4 5 6"); 29 | mystl::istream_iterator beg{istream}, end; 30 | for (; beg != end; ++beg) { 31 | std::cout << *beg << " "; 32 | } 33 | std::cout << '\n'; 34 | 35 | PASSED; 36 | } 37 | 38 | } // namespace stream_iterator_test 39 | } // namespace test 40 | } // namespace mystl 41 | #endif // !MYTINYSTL_STREAM_ITERATOR_TEST_H_ 42 | 43 | -------------------------------------------------------------------------------- /Test/list_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_LIST_TEST_H_ 2 | #define MYTINYSTL_LIST_TEST_H_ 3 | 4 | // list test : 测试 list 的接口与 insert, sort 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/list.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace list_test 16 | { 17 | 18 | // 一个辅助测试函数 19 | bool is_odd(int x) { return x & 1; } 20 | 21 | void list_test() 22 | { 23 | std::cout << "[===============================================================]" << std::endl; 24 | std::cout << "[------------------ Run container test : list ------------------]" << std::endl; 25 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 26 | int a[] = { 1,2,3,4,5 }; 27 | mystl::list l1; 28 | mystl::list l2(5); 29 | mystl::list l3(5, 1); 30 | mystl::list l4(a, a + 5); 31 | mystl::list l5(l2); 32 | mystl::list l6(std::move(l2)); 33 | mystl::list l7{ 1,2,3,4,5,6,7,8,9 }; 34 | mystl::list l8; 35 | l8 = l3; 36 | mystl::list l9; 37 | l9 = std::move(l3); 38 | mystl::list l10; 39 | l10 = { 1, 2, 2, 3, 5, 6, 7, 8, 9 }; 40 | 41 | FUN_AFTER(l1, l1.assign(8, 8)); 42 | FUN_AFTER(l1, l1.assign(a, a + 5)); 43 | FUN_AFTER(l1, l1.assign({ 1,2,3,4,5,6 })); 44 | FUN_AFTER(l1, l1.insert(l1.end(), 6)); 45 | FUN_AFTER(l1, l1.insert(l1.end(), 2, 7)); 46 | FUN_AFTER(l1, l1.insert(l1.begin(), a, a + 5)); 47 | FUN_AFTER(l1, l1.push_back(2)); 48 | FUN_AFTER(l1, l1.push_front(1)); 49 | FUN_AFTER(l1, l1.emplace(l1.begin(),1)); 50 | FUN_AFTER(l1, l1.emplace_front(0)); 51 | FUN_AFTER(l1, l1.emplace_back(10)); 52 | FUN_VALUE(l1.size()); 53 | FUN_AFTER(l1, l1.pop_front()); 54 | FUN_AFTER(l1, l1.pop_back()); 55 | FUN_AFTER(l1, l1.erase(l1.begin())); 56 | FUN_AFTER(l1, l1.erase(l1.begin(), l1.end())); 57 | FUN_VALUE(l1.size()); 58 | FUN_AFTER(l1, l1.resize(10)); 59 | FUN_AFTER(l1, l1.resize(5, 1)); 60 | FUN_AFTER(l1, l1.resize(8, 2)); 61 | FUN_VALUE(l1.size()); 62 | FUN_AFTER(l1, l1.splice(l1.end(), l4)); 63 | FUN_AFTER(l1, l1.splice(l1.begin(), l5, l5.begin())); 64 | FUN_AFTER(l1, l1.splice(l1.end(), l6, l6.begin(), ++l6.begin())); 65 | FUN_VALUE(l1.size()); 66 | FUN_AFTER(l1, l1.remove(0)); 67 | FUN_AFTER(l1, l1.remove_if(is_odd)); 68 | FUN_VALUE(l1.size()); 69 | FUN_AFTER(l1, l1.assign({ 9,5,3,3,7,1,3,2,2,0,10 })); 70 | FUN_VALUE(l1.size()); 71 | FUN_AFTER(l1, l1.sort()); 72 | FUN_AFTER(l1, l1.unique()); 73 | FUN_AFTER(l1, l1.unique([&](int a, int b) {return b == a + 1; })); 74 | FUN_AFTER(l1, l1.merge(l7)); 75 | FUN_AFTER(l1, l1.sort(mystl::greater())); 76 | FUN_AFTER(l1, l1.merge(l8, mystl::greater())); 77 | FUN_AFTER(l1, l1.reverse()); 78 | FUN_AFTER(l1, l1.clear()); 79 | FUN_AFTER(l1, l1.swap(l9)); 80 | FUN_VALUE(*l1.begin()); 81 | FUN_VALUE(*l1.rbegin()); 82 | FUN_VALUE(l1.front()); 83 | FUN_VALUE(l1.back()); 84 | std::cout << std::boolalpha; 85 | FUN_VALUE(l1.empty()); 86 | std::cout << std::noboolalpha; 87 | FUN_VALUE(l1.size()); 88 | FUN_VALUE(l1.max_size()); 89 | PASSED; 90 | #if PERFORMANCE_TEST_ON 91 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 92 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 93 | std::cout << "| insert |"; 94 | #if LARGER_TEST_DATA_ON 95 | CON_TEST_P2(list, insert, end, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 96 | #else 97 | CON_TEST_P2(list, insert, end, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 98 | #endif 99 | std::cout << std::endl; 100 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 101 | std::cout << "| sort |"; 102 | #if LARGER_TEST_DATA_ON 103 | LIST_SORT_TEST(SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 104 | #else 105 | LIST_SORT_TEST(SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 106 | #endif 107 | std::cout << std::endl; 108 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 109 | PASSED; 110 | #endif 111 | std::cout << "[------------------ End container test : list ------------------]" << std::endl; 112 | } 113 | 114 | } // namespace list_test 115 | } // namespace test 116 | } // namespace mystl 117 | #endif // !MYTINYSTL_LIST_TEST_H_ 118 | 119 | -------------------------------------------------------------------------------- /Test/map_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_MAP_TEST_H_ 2 | #define MYTINYSTL_MAP_TEST_H_ 3 | 4 | // map test : 测试 map, multimap 的接口与它们 insert 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/map.h" 9 | #include "../MyTinySTL/vector.h" 10 | #include "test.h" 11 | 12 | namespace mystl 13 | { 14 | namespace test 15 | { 16 | namespace map_test 17 | { 18 | 19 | // pair 的宏定义 20 | #define PAIR mystl::pair 21 | 22 | // map 的遍历输出 23 | #define MAP_COUT(m) do { \ 24 | std::string m_name = #m; \ 25 | std::cout << " " << m_name << " :"; \ 26 | for (auto it : m) std::cout << " <" << it.first << "," << it.second << ">"; \ 27 | std::cout << std::endl; \ 28 | } while(0) 29 | 30 | // map 的函数操作 31 | #define MAP_FUN_AFTER(con, fun) do { \ 32 | std::string str = #fun; \ 33 | std::cout << " After " << str << " :" << std::endl; \ 34 | fun; \ 35 | MAP_COUT(con); \ 36 | } while(0) 37 | 38 | // map 的函数值 39 | #define MAP_VALUE(fun) do { \ 40 | std::string str = #fun; \ 41 | auto it = fun; \ 42 | std::cout << " " << str << " : <" << it.first << "," << it.second << ">\n"; \ 43 | } while(0) 44 | 45 | void map_test() 46 | { 47 | std::cout << "[===============================================================]" << std::endl; 48 | std::cout << "[------------------ Run container test : map -------------------]" << std::endl; 49 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 50 | mystl::vector v; 51 | for (int i = 0; i < 5; ++i) 52 | v.push_back(PAIR(i, i)); 53 | mystl::map m1; 54 | mystl::map> m2; 55 | mystl::map m3(v.begin(), v.end()); 56 | mystl::map m4(v.begin(), v.end()); 57 | mystl::map m5(m3); 58 | mystl::map m6(std::move(m3)); 59 | mystl::map m7; 60 | m7 = m4; 61 | mystl::map m8; 62 | m8 = std::move(m4); 63 | mystl::map m9{ PAIR(1,1),PAIR(3,2),PAIR(2,3) }; 64 | mystl::map m10; 65 | m10 = { PAIR(1,1),PAIR(3,2),PAIR(2,3) }; 66 | 67 | for (int i = 5; i > 0; --i) 68 | { 69 | MAP_FUN_AFTER(m1, m1.emplace(i, i)); 70 | } 71 | MAP_FUN_AFTER(m1, m1.emplace_hint(m1.begin(), 0, 0)); 72 | MAP_FUN_AFTER(m1, m1.erase(m1.begin())); 73 | MAP_FUN_AFTER(m1, m1.erase(0)); 74 | MAP_FUN_AFTER(m1, m1.erase(1)); 75 | MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.end())); 76 | for (int i = 0; i < 5; ++i) 77 | { 78 | MAP_FUN_AFTER(m1, m1.insert(PAIR(i, i))); 79 | } 80 | MAP_FUN_AFTER(m1, m1.insert(v.begin(), v.end())); 81 | MAP_FUN_AFTER(m1, m1.insert(m1.end(), PAIR(5, 5))); 82 | FUN_VALUE(m1.count(1)); 83 | MAP_VALUE(*m1.find(3)); 84 | MAP_VALUE(*m1.lower_bound(3)); 85 | MAP_VALUE(*m1.upper_bound(2)); 86 | auto first = *m1.equal_range(2).first; 87 | auto second = *m1.equal_range(2).second; 88 | std::cout << " m1.equal_range(2) : from <" << first.first << ", " << first.second 89 | << "> to <" << second.first << ", " << second.second << ">" << std::endl; 90 | MAP_FUN_AFTER(m1, m1.erase(m1.begin())); 91 | MAP_FUN_AFTER(m1, m1.erase(1)); 92 | MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.find(3))); 93 | MAP_FUN_AFTER(m1, m1.clear()); 94 | MAP_FUN_AFTER(m1, m1.swap(m9)); 95 | MAP_VALUE(*m1.begin()); 96 | MAP_VALUE(*m1.rbegin()); 97 | FUN_VALUE(m1[1]); 98 | MAP_FUN_AFTER(m1, m1[1] = 3); 99 | FUN_VALUE(m1.at(1)); 100 | std::cout << std::boolalpha; 101 | FUN_VALUE(m1.empty()); 102 | std::cout << std::noboolalpha; 103 | FUN_VALUE(m1.size()); 104 | FUN_VALUE(m1.max_size()); 105 | PASSED; 106 | #if PERFORMANCE_TEST_ON 107 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 108 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 109 | std::cout << "| emplace |"; 110 | #if LARGER_TEST_DATA_ON 111 | MAP_EMPLACE_TEST(map, SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 112 | #else 113 | MAP_EMPLACE_TEST(map, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 114 | #endif 115 | std::cout << std::endl; 116 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 117 | PASSED; 118 | #endif 119 | std::cout << "[------------------ End container test : map -------------------]" << std::endl; 120 | } 121 | 122 | void multimap_test() 123 | { 124 | std::cout << "[===============================================================]" << std::endl; 125 | std::cout << "[---------------- Run container test : multimap ----------------]" << std::endl; 126 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 127 | mystl::vector v; 128 | for (int i = 0; i < 5; ++i) 129 | v.push_back(PAIR(i, i)); 130 | mystl::multimap m1; 131 | mystl::multimap> m2; 132 | mystl::multimap m3(v.begin(), v.end()); 133 | mystl::multimap m4(v.begin(), v.end()); 134 | mystl::multimap m5(m3); 135 | mystl::multimap m6(std::move(m3)); 136 | mystl::multimap m7; 137 | m7 = m4; 138 | mystl::multimap m8; 139 | m8 = std::move(m4); 140 | mystl::multimap m9{ PAIR(1,1),PAIR(3,2),PAIR(2,3) }; 141 | mystl::multimap m10; 142 | m10 = { PAIR(1,1),PAIR(3,2),PAIR(2,3) }; 143 | 144 | for (int i = 5; i > 0; --i) 145 | { 146 | MAP_FUN_AFTER(m1, m1.emplace(i, i)); 147 | } 148 | MAP_FUN_AFTER(m1, m1.emplace_hint(m1.begin(), 0, 0)); 149 | MAP_FUN_AFTER(m1, m1.erase(m1.begin())); 150 | MAP_FUN_AFTER(m1, m1.erase(0)); 151 | MAP_FUN_AFTER(m1, m1.erase(1)); 152 | MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.end())); 153 | for (int i = 0; i < 5; ++i) 154 | { 155 | MAP_FUN_AFTER(m1, m1.insert(mystl::make_pair(i, i))); 156 | } 157 | MAP_FUN_AFTER(m1, m1.insert(v.begin(), v.end())); 158 | MAP_FUN_AFTER(m1, m1.insert(PAIR(5, 5))); 159 | MAP_FUN_AFTER(m1, m1.insert(m1.end(), PAIR(5, 5))); 160 | FUN_VALUE(m1.count(3)); 161 | MAP_VALUE(*m1.find(3)); 162 | MAP_VALUE(*m1.lower_bound(3)); 163 | MAP_VALUE(*m1.upper_bound(2)); 164 | auto first = *m1.equal_range(2).first; 165 | auto second = *m1.equal_range(2).second; 166 | std::cout << " m1.equal_range(2) : from <" << first.first << ", " << first.second 167 | << "> to <" << second.first << ", " << second.second << ">" << std::endl; 168 | MAP_FUN_AFTER(m1, m1.erase(m1.begin())); 169 | MAP_FUN_AFTER(m1, m1.erase(1)); 170 | MAP_FUN_AFTER(m1, m1.erase(m1.begin(), m1.find(3))); 171 | MAP_FUN_AFTER(m1, m1.clear()); 172 | MAP_FUN_AFTER(m1, m1.swap(m9)); 173 | MAP_FUN_AFTER(m1, m1.insert(PAIR(3, 3))); 174 | MAP_VALUE(*m1.begin()); 175 | MAP_VALUE(*m1.rbegin()); 176 | std::cout << std::boolalpha; 177 | FUN_VALUE(m1.empty()); 178 | std::cout << std::noboolalpha; 179 | FUN_VALUE(m1.size()); 180 | FUN_VALUE(m1.max_size()); 181 | PASSED; 182 | #if PERFORMANCE_TEST_ON 183 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 184 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 185 | std::cout << "| emplace |"; 186 | #if LARGER_TEST_DATA_ON 187 | MAP_EMPLACE_TEST(multimap, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 188 | #else 189 | MAP_EMPLACE_TEST(multimap, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 190 | #endif 191 | std::cout << std::endl; 192 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 193 | PASSED; 194 | #endif 195 | std::cout << "[---------------- End container test : multimap ----------------]" << std::endl; 196 | } 197 | 198 | } // namespace map_test 199 | } // namespace test 200 | } // namespace mystl 201 | #endif // !MYTINYSTL_MAP_TEST_H_ 202 | 203 | -------------------------------------------------------------------------------- /Test/queue_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_QUEUE_TEST_H_ 2 | #define MYTINYSTL_QUEUE_TEST_H_ 3 | 4 | // queue test : 测试 queue, priority_queue 的接口和它们 push 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/queue.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace queue_test 16 | { 17 | 18 | void queue_print(mystl::queue q) 19 | { 20 | while (!q.empty()) 21 | { 22 | std::cout << " " << q.front(); 23 | q.pop(); 24 | } 25 | std::cout << std::endl; 26 | } 27 | 28 | void p_queue_print(mystl::priority_queue p) 29 | { 30 | while (!p.empty()) 31 | { 32 | std::cout << " " << p.top(); 33 | p.pop(); 34 | } 35 | std::cout << std::endl; 36 | } 37 | 38 | // queue 的遍历输出 39 | #define QUEUE_COUT(q) do { \ 40 | std::string q_name = #q; \ 41 | std::cout << " " << q_name << " :"; \ 42 | queue_print(q); \ 43 | } while(0) 44 | 45 | // priority_queue 的遍历输出 46 | #define P_QUEUE_COUT(p) do { \ 47 | std::string p_name = #p; \ 48 | std::cout << " " << p_name << " :"; \ 49 | p_queue_print(p); \ 50 | } while(0) 51 | 52 | #define QUEUE_FUN_AFTER(con, fun) do { \ 53 | std::string fun_name = #fun; \ 54 | std::cout << " After " << fun_name << " :\n"; \ 55 | fun; \ 56 | QUEUE_COUT(con); \ 57 | } while(0) 58 | 59 | #define P_QUEUE_FUN_AFTER(con, fun) do { \ 60 | std::string fun_name = #fun; \ 61 | std::cout << " After " << fun_name << " :\n"; \ 62 | fun; \ 63 | P_QUEUE_COUT(con); \ 64 | } while(0) 65 | 66 | void queue_test() 67 | { 68 | std::cout << "[===============================================================]" << std::endl; 69 | std::cout << "[----------------- Run container test : queue ------------------]" << std::endl; 70 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 71 | int a[] = { 1,2,3,4,5 }; 72 | mystl::deque d1(5); 73 | mystl::queue q1; 74 | mystl::queue q2(5); 75 | mystl::queue q3(5, 1); 76 | mystl::queue q4(a, a + 5); 77 | mystl::queue q5(d1); 78 | mystl::queue q6(std::move(d1)); 79 | mystl::queue q7(q2); 80 | mystl::queue q8(std::move(q2)); 81 | mystl::queue q9; 82 | q9 = q3; 83 | mystl::queue q10; 84 | q10 = std::move(q3); 85 | mystl::queue q11{ 1,2,3,4,5 }; 86 | mystl::queue q12; 87 | q12 = { 1,2,3,4,5 }; 88 | 89 | QUEUE_FUN_AFTER(q1, q1.push(1)); 90 | QUEUE_FUN_AFTER(q1, q1.push(2)); 91 | QUEUE_FUN_AFTER(q1, q1.push(3)); 92 | QUEUE_FUN_AFTER(q1, q1.pop()); 93 | QUEUE_FUN_AFTER(q1, q1.emplace(4)); 94 | QUEUE_FUN_AFTER(q1, q1.emplace(5)); 95 | std::cout << std::boolalpha; 96 | FUN_VALUE(q1.empty()); 97 | std::cout << std::noboolalpha; 98 | FUN_VALUE(q1.size()); 99 | FUN_VALUE(q1.front()); 100 | FUN_VALUE(q1.back()); 101 | while (!q1.empty()) 102 | { 103 | QUEUE_FUN_AFTER(q1, q1.pop()); 104 | } 105 | QUEUE_FUN_AFTER(q1, q1.swap(q4)); 106 | QUEUE_FUN_AFTER(q1, q1.clear()); 107 | PASSED; 108 | #if PERFORMANCE_TEST_ON 109 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 110 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 111 | std::cout << "| push |"; 112 | #if LARGER_TEST_DATA_ON 113 | CON_TEST_P1(queue, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 114 | #else 115 | CON_TEST_P1(queue, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 116 | #endif 117 | std::cout << std::endl; 118 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 119 | PASSED; 120 | #endif 121 | std::cout << "[----------------- End container test : queue ------------------]" << std::endl; 122 | } 123 | 124 | void priority_test() 125 | { 126 | std::cout << "[===============================================================]" << std::endl; 127 | std::cout << "[------------- Run container test : priority_queue -------------]" << std::endl; 128 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 129 | int a[] = { 1,2,3,4,5 }; 130 | mystl::vector v1(5); 131 | mystl::priority_queue p1; 132 | mystl::priority_queue p2(5); 133 | mystl::priority_queue p3(5, 1); 134 | mystl::priority_queue p4(a, a + 5); 135 | mystl::priority_queue p5(v1); 136 | mystl::priority_queue p6(std::move(v1)); 137 | mystl::priority_queue p7(p2); 138 | mystl::priority_queue p8(std::move(p2)); 139 | mystl::priority_queue p9; 140 | p9 = p3; 141 | mystl::priority_queue p10; 142 | p10 = std::move(p3); 143 | mystl::priority_queue p11{ 1,2,3,4,5 }; 144 | mystl::priority_queue p12; 145 | p12 = { 1,2,3,4,5 }; 146 | 147 | P_QUEUE_FUN_AFTER(p1, p1.push(1)); 148 | P_QUEUE_FUN_AFTER(p1, p1.push(5)); 149 | P_QUEUE_FUN_AFTER(p1, p1.push(3)); 150 | P_QUEUE_FUN_AFTER(p1, p1.pop()); 151 | P_QUEUE_FUN_AFTER(p1, p1.emplace(7)); 152 | P_QUEUE_FUN_AFTER(p1, p1.emplace(2)); 153 | P_QUEUE_FUN_AFTER(p1, p1.emplace(8)); 154 | std::cout << std::boolalpha; 155 | FUN_VALUE(p1.empty()); 156 | std::cout << std::noboolalpha; 157 | FUN_VALUE(p1.size()); 158 | FUN_VALUE(p1.top()); 159 | while (!p1.empty()) 160 | { 161 | P_QUEUE_FUN_AFTER(p1, p1.pop()); 162 | } 163 | P_QUEUE_FUN_AFTER(p1, p1.swap(p4)); 164 | P_QUEUE_FUN_AFTER(p1, p1.clear()); 165 | PASSED; 166 | #if PERFORMANCE_TEST_ON 167 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 168 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 169 | std::cout << "| push |"; 170 | #if LARGER_TEST_DATA_ON 171 | CON_TEST_P1(priority_queue, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 172 | #else 173 | CON_TEST_P1(priority_queue, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 174 | #endif 175 | std::cout << std::endl; 176 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 177 | PASSED; 178 | #endif 179 | std::cout << "[------------- End container test : priority_queue -------------]" << std::endl; 180 | } 181 | 182 | } // namespace queue_test 183 | } // namespace test 184 | } // namespace mystl 185 | #endif // !MYTINYSTL_QUEUE_TEST_H_ 186 | 187 | -------------------------------------------------------------------------------- /Test/set_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_SET_TEST_H_ 2 | #define MYTINYSTL_SET_TEST_H_ 3 | 4 | // set test : 测试 set, multiset 的接口与它们 insert 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/set.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace set_test 16 | { 17 | 18 | void set_test() 19 | { 20 | std::cout << "[===============================================================]" << std::endl; 21 | std::cout << "[------------------ Run container test : set -------------------]" << std::endl; 22 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 23 | int a[] = { 5,4,3,2,1 }; 24 | mystl::set s1; 25 | mystl::set> s2; 26 | mystl::set s3(a, a + 5); 27 | mystl::set s4(a, a + 5); 28 | mystl::set s5(s3); 29 | mystl::set s6(std::move(s3)); 30 | mystl::set s7; 31 | s7 = s4; 32 | mystl::set s8; 33 | s8 = std::move(s4); 34 | mystl::set s9{ 1,2,3,4,5 }; 35 | mystl::set s10; 36 | s10 = { 1,2,3,4,5 }; 37 | 38 | for (int i = 5; i > 0; --i) 39 | { 40 | FUN_AFTER(s1, s1.emplace(i)); 41 | } 42 | FUN_AFTER(s1, s1.emplace_hint(s1.begin(), 0)); 43 | FUN_AFTER(s1, s1.erase(s1.begin())); 44 | FUN_AFTER(s1, s1.erase(0)); 45 | FUN_AFTER(s1, s1.erase(1)); 46 | FUN_AFTER(s1, s1.erase(s1.begin(), s1.end())); 47 | for (int i = 0; i < 5; ++i) 48 | { 49 | FUN_AFTER(s1, s1.insert(i)); 50 | } 51 | FUN_AFTER(s1, s1.insert(a, a + 5)); 52 | FUN_AFTER(s1, s1.insert(5)); 53 | FUN_AFTER(s1, s1.insert(s1.end(), 5)); 54 | FUN_VALUE(s1.count(5)); 55 | FUN_VALUE(*s1.find(3)); 56 | FUN_VALUE(*s1.lower_bound(3)); 57 | FUN_VALUE(*s1.upper_bound(3)); 58 | auto first = *s1.equal_range(3).first; 59 | auto second = *s1.equal_range(3).second; 60 | std::cout << " s1.equal_range(3) : from " << first << " to " << second << std::endl; 61 | FUN_AFTER(s1, s1.erase(s1.begin())); 62 | FUN_AFTER(s1, s1.erase(1)); 63 | FUN_AFTER(s1, s1.erase(s1.begin(), s1.find(3))); 64 | FUN_AFTER(s1, s1.clear()); 65 | FUN_AFTER(s1, s1.swap(s5)); 66 | FUN_VALUE(*s1.begin()); 67 | FUN_VALUE(*s1.rbegin()); 68 | std::cout << std::boolalpha; 69 | FUN_VALUE(s1.empty()); 70 | std::cout << std::noboolalpha; 71 | FUN_VALUE(s1.size()); 72 | FUN_VALUE(s1.max_size()); 73 | PASSED; 74 | #if PERFORMANCE_TEST_ON 75 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 76 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 77 | std::cout << "| emplace |"; 78 | #if LARGER_TEST_DATA_ON 79 | CON_TEST_P1(set, emplace, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 80 | #else 81 | CON_TEST_P1(set, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 82 | #endif 83 | std::cout << std::endl; 84 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 85 | PASSED; 86 | #endif 87 | std::cout << "[------------------ End container test : set -------------------]" << std::endl; 88 | } 89 | 90 | void multiset_test() 91 | { 92 | std::cout << "[===============================================================]" << std::endl; 93 | std::cout << "[---------------- Run container test : multiset ----------------]" << std::endl; 94 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 95 | int a[] = { 5,4,3,2,1 }; 96 | mystl::multiset s1; 97 | mystl::multiset> s2; 98 | mystl::multiset s3(a, a + 5); 99 | mystl::multiset s4(a, a + 5); 100 | mystl::multiset s5(s3); 101 | mystl::multiset s6(std::move(s3)); 102 | mystl::multiset s7; 103 | s7 = s4; 104 | mystl::multiset s8; 105 | s8 = std::move(s4); 106 | mystl::multiset s9{ 1,2,3,4,5 }; 107 | mystl::multiset s10; 108 | s10 = { 1,2,3,4,5 }; 109 | 110 | for (int i = 5; i > 0; --i) 111 | { 112 | FUN_AFTER(s1, s1.emplace(i)); 113 | } 114 | FUN_AFTER(s1, s1.emplace_hint(s1.begin(), 0)); 115 | FUN_AFTER(s1, s1.erase(s1.begin())); 116 | FUN_AFTER(s1, s1.erase(0)); 117 | FUN_AFTER(s1, s1.erase(1)); 118 | FUN_AFTER(s1, s1.erase(s1.begin(), s1.end())); 119 | for (int i = 0; i < 5; ++i) 120 | { 121 | FUN_AFTER(s1, s1.insert(i)); 122 | } 123 | FUN_AFTER(s1, s1.insert(a, a + 5)); 124 | FUN_AFTER(s1, s1.insert(5)); 125 | FUN_AFTER(s1, s1.insert(s1.end(), 5)); 126 | FUN_VALUE(s1.count(5)); 127 | FUN_VALUE(*s1.find(3)); 128 | FUN_VALUE(*s1.lower_bound(3)); 129 | FUN_VALUE(*s1.upper_bound(3)); 130 | auto first = *s1.equal_range(3).first; 131 | auto second = *s1.equal_range(3).second; 132 | std::cout << " s1.equal_range(3) : from " << first << " to " << second << std::endl; 133 | FUN_AFTER(s1, s1.erase(s1.begin())); 134 | FUN_AFTER(s1, s1.erase(1)); 135 | FUN_AFTER(s1, s1.erase(s1.begin(), s1.find(3))); 136 | FUN_AFTER(s1, s1.clear()); 137 | FUN_AFTER(s1, s1.swap(s5)); 138 | FUN_VALUE(*s1.begin()); 139 | FUN_VALUE(*s1.rbegin()); 140 | std::cout << std::boolalpha; 141 | FUN_VALUE(s1.empty()); 142 | std::cout << std::noboolalpha; 143 | FUN_VALUE(s1.size()); 144 | FUN_VALUE(s1.max_size()); 145 | PASSED; 146 | #if PERFORMANCE_TEST_ON 147 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 148 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 149 | std::cout << "| emplace |"; 150 | #if LARGER_TEST_DATA_ON 151 | CON_TEST_P1(multiset, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 152 | #else 153 | CON_TEST_P1(multiset, emplace, rand(), SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 154 | #endif 155 | std::cout << std::endl; 156 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 157 | PASSED; 158 | #endif 159 | std::cout << "[---------------- End container test : multiset ----------------]" << std::endl; 160 | } 161 | 162 | } // namespace set_test 163 | } // namespace test 164 | } // namespace mystl 165 | #endif // !MYTINYSTL_SET_TEST_H_ 166 | 167 | -------------------------------------------------------------------------------- /Test/stack_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_STACK_TEST_H_ 2 | #define MYTINYSTL_STACK_TEST_H_ 3 | 4 | // stack test : 测试 stack 的接口 和 push 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/stack.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace stack_test 16 | { 17 | 18 | void stack_print(mystl::stack s) 19 | { 20 | while (!s.empty()) 21 | { 22 | std::cout << " " << s.top(); 23 | s.pop(); 24 | } 25 | std::cout << std::endl; 26 | } 27 | 28 | // stack 的遍历输出 29 | #define STACK_COUT(s) do { \ 30 | std::string s_name = #s; \ 31 | std::cout << " " << s_name << " :"; \ 32 | stack_print(s); \ 33 | } while(0) 34 | 35 | #define STACK_FUN_AFTER(con, fun) do { \ 36 | std::string fun_name = #fun; \ 37 | std::cout << " After " << fun_name << " :\n"; \ 38 | fun; \ 39 | STACK_COUT(con); \ 40 | } while(0) 41 | 42 | void stack_test() 43 | { 44 | std::cout << "[===============================================================]" << std::endl; 45 | std::cout << "[----------------- Run container test : stack ------------------]" << std::endl; 46 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 47 | int a[] = { 1,2,3,4,5 }; 48 | mystl::deque d1(5); 49 | mystl::stack s1; 50 | mystl::stack s2(5); 51 | mystl::stack s3(5, 1); 52 | mystl::stack s4(a, a + 5); 53 | mystl::stack s5(d1); 54 | mystl::stack s6(std::move(d1)); 55 | mystl::stack s7(s2); 56 | mystl::stack s8(std::move(s2)); 57 | mystl::stack s9; 58 | s9 = s3; 59 | mystl::stack s10; 60 | s10 = std::move(s3); 61 | mystl::stack s11{ 1,2,3,4,5 }; 62 | mystl::stack s12; 63 | s12 = { 1,2,3,4,5 }; 64 | 65 | STACK_FUN_AFTER(s1, s1.push(1)); 66 | STACK_FUN_AFTER(s1, s1.push(2)); 67 | STACK_FUN_AFTER(s1, s1.push(3)); 68 | STACK_FUN_AFTER(s1, s1.pop()); 69 | STACK_FUN_AFTER(s1, s1.emplace(4)); 70 | STACK_FUN_AFTER(s1, s1.emplace(5)); 71 | std::cout << std::boolalpha; 72 | FUN_VALUE(s1.empty()); 73 | std::cout << std::noboolalpha; 74 | FUN_VALUE(s1.size()); 75 | FUN_VALUE(s1.top()); 76 | while (!s1.empty()) 77 | { 78 | STACK_FUN_AFTER(s1, s1.pop()); 79 | } 80 | STACK_FUN_AFTER(s1, s1.swap(s4)); 81 | STACK_FUN_AFTER(s1, s1.clear()); 82 | PASSED; 83 | #if PERFORMANCE_TEST_ON 84 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 85 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 86 | std::cout << "| push |"; 87 | #if LARGER_TEST_DATA_ON 88 | CON_TEST_P1(stack, push, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 89 | #else 90 | CON_TEST_P1(stack, push, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 91 | #endif 92 | std::cout << std::endl; 93 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 94 | PASSED; 95 | #endif 96 | std::cout << "[----------------- End container test : stack ------------------]" << std::endl; 97 | } 98 | 99 | } // namespace stack_test 100 | } // namespace test 101 | } // namespace mystl 102 | #endif // !MYTINYSTL_STACK_TEST_H_ 103 | 104 | -------------------------------------------------------------------------------- /Test/string_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_STRING_TEST_H_ 2 | #define MYTINYSTL_STRING_TEST_H_ 3 | 4 | // string test : 测试 string 的接口和 insert 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/astring.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace string_test 16 | { 17 | 18 | void string_test() 19 | { 20 | std::cout << "[===============================================================]" << std::endl; 21 | std::cout << "[----------------- Run container test : string -----------------]" << std::endl; 22 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 23 | const char* s = "abcdefg"; 24 | mystl::string str; 25 | mystl::string str1(5, 'a'); 26 | mystl::string str2(str1, 3); 27 | mystl::string str3(str1, 0, 3); 28 | mystl::string str4("abc"); 29 | mystl::string str5("abcde",3); 30 | mystl::string str6(s, s + 5); 31 | mystl::string str7(str1); 32 | mystl::string str8(std::move(str1)); 33 | mystl::string str9; 34 | str9 = str2; 35 | mystl::string str10; 36 | str10 = std::move(str2); 37 | mystl::string str11; 38 | str11 = "123"; 39 | mystl::string str12; 40 | str12 = 'A'; 41 | 42 | STR_FUN_AFTER(str, str = 'a'); 43 | STR_FUN_AFTER(str, str = "string"); 44 | FUN_VALUE(*str.begin()); 45 | FUN_VALUE(*str.rbegin()); 46 | FUN_VALUE(*(str.end() - 1)); 47 | FUN_VALUE(*(str.rend() - 1)); 48 | FUN_VALUE(str.front()); 49 | FUN_VALUE(str.back()); 50 | FUN_VALUE(str[1]); 51 | FUN_VALUE(str.at(2)); 52 | STR_COUT(str.data()); 53 | STR_COUT(str.c_str()); 54 | std::cout << std::boolalpha; 55 | FUN_VALUE(str.empty()); 56 | std::cout << std::noboolalpha; 57 | FUN_VALUE(str.size()); 58 | FUN_VALUE(str.length()); 59 | FUN_VALUE(str.capacity()); 60 | FUN_VALUE(str.max_size()); 61 | STR_FUN_AFTER(str, str.shrink_to_fit()); 62 | FUN_VALUE(str.capacity()); 63 | 64 | STR_FUN_AFTER(str, str.insert(str.begin(), 'a')); 65 | STR_FUN_AFTER(str, str.insert(str.end(), 3, 'x')); 66 | STR_FUN_AFTER(str, str.insert(str.end(), s, s + 3)); 67 | STR_FUN_AFTER(str, str.erase(str.begin())); 68 | STR_FUN_AFTER(str, str.erase(str.begin(), str.begin() + 3)); 69 | STR_FUN_AFTER(str, str.clear()); 70 | STR_FUN_AFTER(str, str.push_back('s')); 71 | STR_FUN_AFTER(str, str.push_back('t')); 72 | STR_FUN_AFTER(str, str.pop_back()); 73 | STR_FUN_AFTER(str, str.append(1, 't')); 74 | STR_FUN_AFTER(str, str.append(str4)); 75 | STR_FUN_AFTER(str, str.append(str4, 1)); 76 | STR_FUN_AFTER(str, str.append(str4, 2, 1)); 77 | STR_FUN_AFTER(str, str.append("str")); 78 | STR_FUN_AFTER(str, str.append("inging", 3)); 79 | STR_FUN_AFTER(str, str.append(s, s + 3)); 80 | STR_FUN_AFTER(str, str.resize(10)); 81 | FUN_VALUE(str.size()); 82 | STR_FUN_AFTER(str, str.resize(20, 'x')); 83 | FUN_VALUE(str.size()); 84 | STR_FUN_AFTER(str, str.clear()); 85 | 86 | STR_FUN_AFTER(str, str = "string"); 87 | STR_FUN_AFTER(str3, str3 = "astrings"); 88 | FUN_VALUE(str.compare(str3)); 89 | FUN_VALUE(str.compare(0, 6, str3)); 90 | FUN_VALUE(str.compare(0, 6, str3, 1, 6)); 91 | FUN_VALUE(str.compare("atringgg")); 92 | FUN_VALUE(str.compare("zzz")); 93 | FUN_VALUE(str.compare(0, 3, "str")); 94 | FUN_VALUE(str.compare(0, 3, "stri", 4)); 95 | FUN_VALUE(str.compare(0, 3, "s", 2)); 96 | FUN_VALUE(str.compare(0, 9, "stringabc", 9)); 97 | FUN_VALUE(str.substr(0)); 98 | FUN_VALUE(str.substr(3)); 99 | FUN_VALUE(str.substr(0, 3)); 100 | FUN_VALUE(str.substr(0, 10)); 101 | STR_FUN_AFTER(str, str.replace(0, 6, str3)); 102 | STR_FUN_AFTER(str, str.replace(str.end() - 1, str.end(), str3)); 103 | STR_FUN_AFTER(str, str.replace(0, 1, "my ")); 104 | STR_FUN_AFTER(str, str.replace(str.end() - 8, str.end(), " test")); 105 | STR_FUN_AFTER(str, str.replace(10, 4, "replace")); 106 | STR_FUN_AFTER(str, str.replace(str.end(), str.end(), " test")); 107 | STR_FUN_AFTER(str, str.replace(0, 2, 3, '6')); 108 | STR_FUN_AFTER(str, str.replace(str.begin(), str.begin() + 3, 6, '6')); 109 | STR_FUN_AFTER(str, str.replace(0, 3, str3, 1, 3)); 110 | STR_FUN_AFTER(str, str.replace(str.begin(), str.begin() + 6, s, s + 3)); 111 | STR_FUN_AFTER(str, str.reverse()); 112 | STR_FUN_AFTER(str, str.reverse()); 113 | 114 | STR_FUN_AFTER(str, str = "abcabc stringgg"); 115 | STR_FUN_AFTER(str3, str3 = "abc"); 116 | FUN_VALUE(str.find('a')); 117 | FUN_VALUE(str.find('a', 3)); 118 | FUN_VALUE(str.find('a', 4)); 119 | FUN_VALUE(str.find("abc")); 120 | FUN_VALUE(str.find("abc", 1)); 121 | FUN_VALUE(str.find("abc", 1, 1)); 122 | FUN_VALUE(str.find(str3)); 123 | FUN_VALUE(str.find(str3, 1)); 124 | FUN_VALUE(str.rfind('g')); 125 | FUN_VALUE(str.rfind('g', 3)); 126 | FUN_VALUE(str.rfind("gg")); 127 | FUN_VALUE(str.rfind("bc", 10)); 128 | FUN_VALUE(str.rfind(str3)); 129 | FUN_VALUE(str.rfind(str3, 3)); 130 | FUN_VALUE(str.find_first_of('g')); 131 | FUN_VALUE(str.find_first_of('k')); 132 | FUN_VALUE(str.find_first_of("bca")); 133 | FUN_VALUE(str.find_first_of("defg", 10)); 134 | FUN_VALUE(str.find_first_of("gnirts")); 135 | FUN_VALUE(str.find_first_of("abc", 6)); 136 | FUN_VALUE(str.find_first_of("abcdf", 2, 3)); 137 | FUN_VALUE(str.find_first_of(str3, 1)); 138 | FUN_VALUE(str.find_first_of(str3, 10)); 139 | FUN_VALUE(str.find_first_not_of('a')); 140 | FUN_VALUE(str.find_first_not_of('d')); 141 | FUN_VALUE(str.find_first_not_of('g', 14)); 142 | FUN_VALUE(str.find_first_not_of("abc")); 143 | FUN_VALUE(str.find_first_not_of("ggggg", 14, 4)); 144 | FUN_VALUE(str.find_first_not_of(str3)); 145 | FUN_VALUE(str.find_first_not_of(str3, 3)); 146 | FUN_VALUE(str.find_last_of('a')); 147 | FUN_VALUE(str.find_last_of('a', 4)); 148 | FUN_VALUE(str.find_last_of('g')); 149 | FUN_VALUE(str.find_last_of("gg")); 150 | FUN_VALUE(str.find_last_of("gg", 14)); 151 | FUN_VALUE(str.find_last_of("ggg", 14, 1)); 152 | FUN_VALUE(str.find_last_of(str3)); 153 | FUN_VALUE(str.find_last_of(str3, 3)); 154 | FUN_VALUE(str.find_last_not_of('g')); 155 | FUN_VALUE(str.find_last_not_of('a')); 156 | FUN_VALUE(str.find_last_not_of('a', 1)); 157 | FUN_VALUE(str.find_last_not_of("ggg")); 158 | FUN_VALUE(str.find_last_not_of("ggg", 14)); 159 | FUN_VALUE(str.find_last_not_of("abc", 3, 1)); 160 | FUN_VALUE(str.find_last_not_of(str3)); 161 | FUN_VALUE(str.find_last_not_of(str3, 2)); 162 | FUN_VALUE(str.count('a')); 163 | FUN_VALUE(str.count('a', 2)); 164 | FUN_VALUE(str.count('d', 10)); 165 | 166 | STR_FUN_AFTER(str, str.swap(str3)); 167 | FUN_VALUE(str.size()); 168 | FUN_VALUE(str.length()); 169 | FUN_VALUE(str.capacity()); 170 | STR_FUN_AFTER(str, str += str); 171 | STR_FUN_AFTER(str, str += 'a'); 172 | STR_FUN_AFTER(str, str += "bc"); 173 | FUN_VALUE(str.size()); 174 | FUN_VALUE(str.length()); 175 | FUN_VALUE(str.capacity()); 176 | STR_FUN_AFTER(str, str.shrink_to_fit()); 177 | FUN_VALUE(str.capacity()); 178 | STR_FUN_AFTER(str, str.reserve(50)); 179 | FUN_VALUE(str.capacity()); 180 | STR_FUN_AFTER(str3, str3 = "test"); 181 | STR_FUN_AFTER(str4, str4 = " ok!"); 182 | std::cout << " str3 + '!' : " << str3 + '!' << std::endl; 183 | std::cout << " '#' + str3 : " << '#' + str3 << std::endl; 184 | std::cout << " str3 + \" success\" : " << str3 + " success" << std::endl; 185 | std::cout << " \"My \" + str3 : " << "My " + str3 << std::endl; 186 | std::cout << " str3 + str4 : " << str3 + str4 << std::endl; 187 | PASSED; 188 | #if PERFORMANCE_TEST_ON 189 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 190 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 191 | std::cout << "| append |"; 192 | #if LARGER_TEST_DATA_ON 193 | CON_TEST_P1(string, append, "s", SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 194 | #else 195 | CON_TEST_P1(string, append, "s", SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 196 | #endif 197 | std::cout << std::endl; 198 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 199 | PASSED; 200 | #endif 201 | std::cout << "[----------------- End container test : string -----------------]" << std::endl; 202 | } 203 | 204 | } // namespace string_test 205 | } // namespace test 206 | } // namespace mystl 207 | #endif // !MYTINYSTL_STRING_TEST_H_ 208 | -------------------------------------------------------------------------------- /Test/test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #define _SCL_SECURE_NO_WARNINGS 3 | #endif 4 | 5 | #if defined(_MSC_VER) && defined(_DEBUG) 6 | #define _CRTDBG_MAP_ALLOC 7 | #include 8 | #include 9 | #endif // check memory leaks 10 | 11 | #include "algorithm_performance_test.h" 12 | #include "algorithm_test.h" 13 | #include "vector_test.h" 14 | #include "list_test.h" 15 | #include "deque_test.h" 16 | #include "queue_test.h" 17 | #include "stack_test.h" 18 | #include "map_test.h" 19 | #include "set_test.h" 20 | #include "unordered_map_test.h" 21 | #include "unordered_set_test.h" 22 | #include "string_test.h" 23 | #include "iterator_test.h" 24 | 25 | int main() 26 | { 27 | using namespace mystl::test; 28 | 29 | std::cout.sync_with_stdio(false); 30 | 31 | RUN_ALL_TESTS(); 32 | algorithm_performance_test::algorithm_performance_test(); 33 | iterator_test::stream_iterator_test(); 34 | vector_test::vector_test(); 35 | list_test::list_test(); 36 | deque_test::deque_test(); 37 | queue_test::queue_test(); 38 | queue_test::priority_test(); 39 | stack_test::stack_test(); 40 | map_test::map_test(); 41 | map_test::multimap_test(); 42 | set_test::set_test(); 43 | set_test::multiset_test(); 44 | unordered_map_test::unordered_map_test(); 45 | unordered_map_test::unordered_multimap_test(); 46 | unordered_set_test::unordered_set_test(); 47 | unordered_set_test::unordered_multiset_test(); 48 | string_test::string_test(); 49 | 50 | #if defined(_MSC_VER) && defined(_DEBUG) 51 | _CrtDumpMemoryLeaks(); 52 | #endif // check memory leaks 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Test/unordered_map_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_UNORDERED_MAP_TEST_H_ 2 | #define MYTINYSTL_UNORDERED_MAP_TEST_H_ 3 | 4 | // unordered_map test : 测试 unordered_map, unordered_multimap 的接口与它们 insert 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/unordered_map.h" 9 | #include "map_test.h" 10 | #include "test.h" 11 | 12 | namespace mystl 13 | { 14 | namespace test 15 | { 16 | namespace unordered_map_test 17 | { 18 | 19 | void unordered_map_test() 20 | { 21 | std::cout << "[===============================================================]" << std::endl; 22 | std::cout << "[-------------- Run container test : unordered_map -------------]" << std::endl; 23 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 24 | mystl::vector v; 25 | for (int i = 0; i < 5; ++i) 26 | v.push_back(PAIR(5 - i, 5 - i)); 27 | mystl::unordered_map um1; 28 | mystl::unordered_map um2(520); 29 | mystl::unordered_map um3(520, mystl::hash()); 30 | mystl::unordered_map um4(520, mystl::hash(), mystl::equal_to()); 31 | mystl::unordered_map um5(v.begin(), v.end()); 32 | mystl::unordered_map um6(v.begin(), v.end(), 100); 33 | mystl::unordered_map um7(v.begin(), v.end(), 100, mystl::hash()); 34 | mystl::unordered_map um8(v.begin(), v.end(), 100, mystl::hash(), mystl::equal_to()); 35 | mystl::unordered_map um9(um5); 36 | mystl::unordered_map um10(std::move(um5)); 37 | mystl::unordered_map um11; 38 | um11 = um6; 39 | mystl::unordered_map um12; 40 | um12 = std::move(um6); 41 | mystl::unordered_map um13{ PAIR(1,1),PAIR(2,3),PAIR(3,3) }; 42 | mystl::unordered_map um14; 43 | um14 = { PAIR(1,1),PAIR(2,3),PAIR(3,3) }; 44 | 45 | MAP_FUN_AFTER(um1, um1.emplace(1, 1)); 46 | MAP_FUN_AFTER(um1, um1.emplace_hint(um1.begin(), 1, 2)); 47 | MAP_FUN_AFTER(um1, um1.insert(PAIR(2, 2))); 48 | MAP_FUN_AFTER(um1, um1.insert(um1.end(), PAIR(3, 3))); 49 | MAP_FUN_AFTER(um1, um1.insert(v.begin(), v.end())); 50 | MAP_FUN_AFTER(um1, um1.erase(um1.begin())); 51 | MAP_FUN_AFTER(um1, um1.erase(um1.begin(), um1.find(3))); 52 | MAP_FUN_AFTER(um1, um1.erase(1)); 53 | std::cout << std::boolalpha; 54 | FUN_VALUE(um1.empty()); 55 | std::cout << std::noboolalpha; 56 | FUN_VALUE(um1.size()); 57 | FUN_VALUE(um1.bucket_count()); 58 | FUN_VALUE(um1.max_bucket_count()); 59 | FUN_VALUE(um1.bucket(1)); 60 | FUN_VALUE(um1.bucket_size(um1.bucket(5))); 61 | MAP_FUN_AFTER(um1, um1.clear()); 62 | MAP_FUN_AFTER(um1, um1.swap(um7)); 63 | MAP_VALUE(*um1.begin()); 64 | FUN_VALUE(um1.at(1)); 65 | FUN_VALUE(um1[1]); 66 | std::cout << std::boolalpha; 67 | FUN_VALUE(um1.empty()); 68 | std::cout << std::noboolalpha; 69 | FUN_VALUE(um1.size()); 70 | FUN_VALUE(um1.max_size()); 71 | FUN_VALUE(um1.bucket_count()); 72 | FUN_VALUE(um1.max_bucket_count()); 73 | FUN_VALUE(um1.bucket(1)); 74 | FUN_VALUE(um1.bucket_size(um1.bucket(1))); 75 | MAP_FUN_AFTER(um1, um1.reserve(1000)); 76 | FUN_VALUE(um1.size()); 77 | FUN_VALUE(um1.bucket_count()); 78 | FUN_VALUE(um1.bucket_size(1)); 79 | FUN_VALUE(um1.bucket_size(2)); 80 | FUN_VALUE(um1.bucket_size(3)); 81 | MAP_FUN_AFTER(um1, um1.rehash(150)); 82 | FUN_VALUE(um1.bucket_count()); 83 | FUN_VALUE(um1.count(1)); 84 | MAP_VALUE(*um1.find(3)); 85 | auto first = *um1.equal_range(3).first; 86 | auto second = *um1.equal_range(3).second; 87 | std::cout << " um1.equal_range(3) : from <" << first.first << ", " << first.second 88 | << "> to <" << second.first << ", " << second.second << ">" << std::endl; 89 | FUN_VALUE(um1.load_factor()); 90 | FUN_VALUE(um1.max_load_factor()); 91 | MAP_FUN_AFTER(um1, um1.max_load_factor(1.5f)); 92 | FUN_VALUE(um1.max_load_factor()); 93 | PASSED; 94 | #if PERFORMANCE_TEST_ON 95 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 96 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 97 | std::cout << "| emplace |"; 98 | #if LARGER_TEST_DATA_ON 99 | MAP_EMPLACE_TEST(unordered_map, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 100 | #else 101 | MAP_EMPLACE_TEST(unordered_map, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 102 | #endif 103 | std::cout << std::endl; 104 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 105 | PASSED; 106 | #endif 107 | std::cout << "[-------------- End container test : unordered_map -------------]" << std::endl; 108 | } 109 | 110 | void unordered_multimap_test() 111 | { 112 | std::cout << "[===============================================================]" << std::endl; 113 | std::cout << "[----------- Run container test : unordered_multimap -----------]" << std::endl; 114 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 115 | mystl::vector v; 116 | for (int i = 0; i < 5; ++i) 117 | v.push_back(PAIR(5 - i, 5 - i)); 118 | mystl::unordered_multimap um1; 119 | mystl::unordered_multimap um2(520); 120 | mystl::unordered_multimap um3(520, mystl::hash()); 121 | mystl::unordered_multimap um4(520, mystl::hash(), mystl::equal_to()); 122 | mystl::unordered_multimap um5(v.begin(), v.end()); 123 | mystl::unordered_multimap um6(v.begin(), v.end(), 100); 124 | mystl::unordered_multimap um7(v.begin(), v.end(), 100, mystl::hash()); 125 | mystl::unordered_multimap um8(v.begin(), v.end(), 100, mystl::hash(), mystl::equal_to()); 126 | mystl::unordered_multimap um9(um5); 127 | mystl::unordered_multimap um10(std::move(um5)); 128 | mystl::unordered_multimap um11; 129 | um11 = um6; 130 | mystl::unordered_multimap um12; 131 | um12 = std::move(um6); 132 | mystl::unordered_multimap um13{ PAIR(1,1),PAIR(2,3),PAIR(3,3) }; 133 | mystl::unordered_multimap um14; 134 | um14 = { PAIR(1,1),PAIR(2,3),PAIR(3,3) }; 135 | 136 | MAP_FUN_AFTER(um1, um1.emplace(1, 1)); 137 | MAP_FUN_AFTER(um1, um1.emplace_hint(um1.begin(), 1, 2)); 138 | MAP_FUN_AFTER(um1, um1.insert(PAIR(2, 2))); 139 | MAP_FUN_AFTER(um1, um1.insert(um1.end(), PAIR(3, 3))); 140 | MAP_FUN_AFTER(um1, um1.insert(v.begin(), v.end())); 141 | MAP_FUN_AFTER(um1, um1.erase(um1.begin())); 142 | MAP_FUN_AFTER(um1, um1.erase(um1.begin(), um1.find(3))); 143 | MAP_FUN_AFTER(um1, um1.erase(1)); 144 | std::cout << std::boolalpha; 145 | FUN_VALUE(um1.empty()); 146 | std::cout << std::noboolalpha; 147 | FUN_VALUE(um1.size()); 148 | FUN_VALUE(um1.bucket_count()); 149 | FUN_VALUE(um1.max_bucket_count()); 150 | FUN_VALUE(um1.bucket(1)); 151 | FUN_VALUE(um1.bucket_size(um1.bucket(5))); 152 | MAP_FUN_AFTER(um1, um1.clear()); 153 | MAP_FUN_AFTER(um1, um1.swap(um7)); 154 | MAP_VALUE(*um1.begin()); 155 | std::cout << std::boolalpha; 156 | FUN_VALUE(um1.empty()); 157 | std::cout << std::noboolalpha; 158 | FUN_VALUE(um1.size()); 159 | FUN_VALUE(um1.max_size()); 160 | FUN_VALUE(um1.bucket_count()); 161 | FUN_VALUE(um1.max_bucket_count()); 162 | FUN_VALUE(um1.bucket(1)); 163 | FUN_VALUE(um1.bucket_size(um1.bucket(1))); 164 | MAP_FUN_AFTER(um1, um1.reserve(1000)); 165 | FUN_VALUE(um1.size()); 166 | FUN_VALUE(um1.bucket_count()); 167 | FUN_VALUE(um1.bucket_size(1)); 168 | FUN_VALUE(um1.bucket_size(2)); 169 | FUN_VALUE(um1.bucket_size(3)); 170 | MAP_FUN_AFTER(um1, um1.rehash(150)); 171 | FUN_VALUE(um1.bucket_count()); 172 | FUN_VALUE(um1.count(1)); 173 | MAP_VALUE(*um1.find(3)); 174 | auto first = *um1.equal_range(3).first; 175 | auto second = *um1.equal_range(3).second; 176 | std::cout << " um1.equal_range(3) : from <" << first.first << ", " << first.second 177 | << "> to <" << second.first << ", " << second.second << ">" << std::endl; 178 | FUN_VALUE(um1.load_factor()); 179 | FUN_VALUE(um1.max_load_factor()); 180 | MAP_FUN_AFTER(um1, um1.max_load_factor(1.5f)); 181 | FUN_VALUE(um1.max_load_factor()); 182 | PASSED; 183 | #if PERFORMANCE_TEST_ON 184 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 185 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 186 | std::cout << "| emplace |"; 187 | #if LARGER_TEST_DATA_ON 188 | MAP_EMPLACE_TEST(unordered_multimap, SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 189 | #else 190 | MAP_EMPLACE_TEST(unordered_multimap, SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 191 | #endif 192 | std::cout << std::endl; 193 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 194 | PASSED; 195 | #endif 196 | std::cout << "[----------- End container test : unordered_multimap -----------]" << std::endl; 197 | } 198 | 199 | } // namespace unordered_map_test 200 | } // namespace test 201 | } // namespace mystl 202 | #endif // !MYTINYSTL_UNORDERED_MAP_TEST_H_ 203 | 204 | -------------------------------------------------------------------------------- /Test/unordered_set_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_UNORDERED_SET_TEST_H_ 2 | #define MYTINYSTL_UNORDERED_SET_TEST_H_ 3 | 4 | // unordered_set test : 测试 unordered_set, unordered_multiset 的接口与它们 insert 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/unordered_set.h" 9 | #include "set_test.h" 10 | #include "test.h" 11 | 12 | namespace mystl 13 | { 14 | namespace test 15 | { 16 | namespace unordered_set_test 17 | { 18 | 19 | void unordered_set_test() 20 | { 21 | std::cout << "[===============================================================]" << std::endl; 22 | std::cout << "[-------------- Run container test : unordered_set -------------]" << std::endl; 23 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 24 | int a[] = { 5,4,3,2,1 }; 25 | mystl::unordered_set us1; 26 | mystl::unordered_set us2(520); 27 | mystl::unordered_set us3(520, mystl::hash()); 28 | mystl::unordered_set us4(520, mystl::hash(), mystl::equal_to()); 29 | mystl::unordered_set us5(a, a + 5); 30 | mystl::unordered_set us6(a, a + 5, 100); 31 | mystl::unordered_set us7(a, a + 5, 100, mystl::hash()); 32 | mystl::unordered_set us8(a, a + 5, 100, mystl::hash(), mystl::equal_to()); 33 | mystl::unordered_set us9(us5); 34 | mystl::unordered_set us10(std::move(us5)); 35 | mystl::unordered_set us11; 36 | us11 = us6; 37 | mystl::unordered_set us12; 38 | us12 = std::move(us6); 39 | mystl::unordered_set us13{ 1,2,3,4,5 }; 40 | mystl::unordered_set us14; 41 | us13 = { 1,2,3,4,5 }; 42 | 43 | FUN_AFTER(us1, us1.emplace(1)); 44 | FUN_AFTER(us1, us1.emplace_hint(us1.end(), 2)); 45 | FUN_AFTER(us1, us1.insert(5)); 46 | FUN_AFTER(us1, us1.insert(us1.begin(), 5)); 47 | FUN_AFTER(us1, us1.insert(a, a + 5)); 48 | FUN_AFTER(us1, us1.erase(us1.begin())); 49 | FUN_AFTER(us1, us1.erase(us1.begin(), us1.find(3))); 50 | FUN_AFTER(us1, us1.erase(1)); 51 | std::cout << std::boolalpha; 52 | FUN_VALUE(us1.empty()); 53 | std::cout << std::noboolalpha; 54 | FUN_VALUE(us1.size()); 55 | FUN_VALUE(us1.bucket_count()); 56 | FUN_VALUE(us1.max_bucket_count()); 57 | FUN_VALUE(us1.bucket(1)); 58 | FUN_VALUE(us1.bucket_size(us1.bucket(5))); 59 | FUN_AFTER(us1, us1.clear()); 60 | FUN_AFTER(us1, us1.swap(us7)); 61 | FUN_VALUE(*us1.begin()); 62 | std::cout << std::boolalpha; 63 | FUN_VALUE(us1.empty()); 64 | std::cout << std::noboolalpha; 65 | FUN_VALUE(us1.size()); 66 | FUN_VALUE(us1.max_size()); 67 | FUN_VALUE(us1.bucket_count()); 68 | FUN_AFTER(us1, us1.reserve(1000)); 69 | FUN_VALUE(*us1.begin(us1.bucket(1))); 70 | FUN_VALUE(us1.size()); 71 | FUN_VALUE(us1.bucket_count()); 72 | FUN_VALUE(us1.bucket_size(1)); 73 | FUN_VALUE(us1.bucket_size(2)); 74 | FUN_VALUE(us1.bucket_size(3)); 75 | FUN_AFTER(us1, us1.rehash(150)); 76 | FUN_VALUE(us1.bucket_count()); 77 | FUN_VALUE(us1.count(1)); 78 | FUN_VALUE(*us1.find(3)); 79 | auto first = *us1.equal_range(3).first; 80 | auto second = *us1.equal_range(3).second; 81 | std::cout << " us1.equal_range(3) : from " << first << " to " << second << std::endl; 82 | FUN_VALUE(us1.load_factor()); 83 | FUN_VALUE(us1.max_load_factor()); 84 | FUN_AFTER(us1, us1.max_load_factor(1.5f)); 85 | FUN_VALUE(us1.max_load_factor()); 86 | PASSED; 87 | #if PERFORMANCE_TEST_ON 88 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 89 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 90 | std::cout << "| emplace |"; 91 | #if LARGER_TEST_DATA_ON 92 | CON_TEST_P1(unordered_set, emplace, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 93 | #else 94 | CON_TEST_P1(unordered_set, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 95 | #endif 96 | std::cout << std::endl; 97 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 98 | PASSED; 99 | #endif 100 | std::cout << "[-------------- End container test : unordered_set -------------]" << std::endl; 101 | } 102 | 103 | void unordered_multiset_test() 104 | { 105 | std::cout << "[===============================================================]" << std::endl; 106 | std::cout << "[------------ Run container test : unordered_multiset ----------]" << std::endl; 107 | std::cout << "[-------------------------- API test ---------------------------]" << std::endl; 108 | int a[] = { 5,4,3,2,1 }; 109 | mystl::unordered_multiset us1; 110 | mystl::unordered_multiset us2(520); 111 | mystl::unordered_multiset us3(520, mystl::hash()); 112 | mystl::unordered_multiset us4(520, mystl::hash(), mystl::equal_to()); 113 | mystl::unordered_multiset us5(a, a + 5); 114 | mystl::unordered_multiset us6(a, a + 5, 100); 115 | mystl::unordered_multiset us7(a, a + 5, 100, mystl::hash()); 116 | mystl::unordered_multiset us8(a, a + 5, 100, mystl::hash(), mystl::equal_to()); 117 | mystl::unordered_multiset us9(us5); 118 | mystl::unordered_multiset us10(std::move(us5)); 119 | mystl::unordered_multiset us11; 120 | us11 = us6; 121 | mystl::unordered_multiset us12; 122 | us12 = std::move(us6); 123 | mystl::unordered_multiset us13{ 1,2,3,4,5 }; 124 | mystl::unordered_multiset us14; 125 | us14 = { 1,2,3,4,5 }; 126 | 127 | FUN_AFTER(us1, us1.emplace(1)); 128 | FUN_AFTER(us1, us1.emplace_hint(us1.end(), 2)); 129 | FUN_AFTER(us1, us1.insert(5)); 130 | FUN_AFTER(us1, us1.insert(us1.begin(), 5)); 131 | FUN_AFTER(us1, us1.insert(a, a + 5)); 132 | FUN_AFTER(us1, us1.erase(us1.begin())); 133 | FUN_AFTER(us1, us1.erase(us1.begin(), us1.find(3))); 134 | FUN_AFTER(us1, us1.erase(1)); 135 | std::cout << std::boolalpha; 136 | FUN_VALUE(us1.empty()); 137 | std::cout << std::noboolalpha; 138 | FUN_VALUE(us1.size()); 139 | FUN_VALUE(us1.bucket_count()); 140 | FUN_VALUE(us1.max_bucket_count()); 141 | FUN_VALUE(us1.bucket(1)); 142 | FUN_VALUE(us1.bucket_size(us1.bucket(5))); 143 | FUN_AFTER(us1, us1.clear()); 144 | FUN_AFTER(us1, us1.swap(us7)); 145 | FUN_VALUE(*us1.begin()); 146 | std::cout << std::boolalpha; 147 | FUN_VALUE(us1.empty()); 148 | std::cout << std::noboolalpha; 149 | FUN_VALUE(us1.size()); 150 | FUN_VALUE(us1.max_size()); 151 | FUN_VALUE(us1.bucket_count()); 152 | FUN_AFTER(us1, us1.reserve(1000)); 153 | FUN_VALUE(*us1.begin(us1.bucket(1))); 154 | FUN_VALUE(us1.size()); 155 | FUN_VALUE(us1.bucket_count()); 156 | FUN_VALUE(us1.bucket_size(1)); 157 | FUN_VALUE(us1.bucket_size(2)); 158 | FUN_VALUE(us1.bucket_size(3)); 159 | FUN_AFTER(us1, us1.rehash(150)); 160 | FUN_VALUE(us1.bucket_count()); 161 | FUN_VALUE(us1.count(1)); 162 | FUN_VALUE(*us1.find(3)); 163 | auto first = *us1.equal_range(3).first; 164 | auto second = *us1.equal_range(3).second; 165 | std::cout << " us1.equal_range(3) : from " << first << " to " << second << std::endl; 166 | FUN_VALUE(us1.load_factor()); 167 | FUN_VALUE(us1.max_load_factor()); 168 | FUN_AFTER(us1, us1.max_load_factor(1.5f)); 169 | FUN_VALUE(us1.max_load_factor()); 170 | PASSED; 171 | #if PERFORMANCE_TEST_ON 172 | std::cout << "[--------------------- Performance Testing ---------------------]" << std::endl; 173 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 174 | std::cout << "| emplace |"; 175 | #if LARGER_TEST_DATA_ON 176 | CON_TEST_P1(unordered_multiset, emplace, rand(), SCALE_M(LEN1), SCALE_M(LEN2), SCALE_M(LEN3)); 177 | #else 178 | CON_TEST_P1(unordered_multiset, emplace, rand(), SCALE_S(LEN1), SCALE_S(LEN2), SCALE_S(LEN3)); 179 | #endif 180 | std::cout << std::endl; 181 | std::cout << "|---------------------|-------------|-------------|-------------|" << std::endl; 182 | PASSED; 183 | #endif 184 | std::cout << "[------------ End container test : unordered_multiset ----------]" << std::endl; 185 | } 186 | 187 | } // namespace unordered_set_test 188 | } // namespace test 189 | } // namespace mystl 190 | #endif // !MYTINYSTL_UNORDERED_SET_TEST_H_ 191 | 192 | -------------------------------------------------------------------------------- /Test/vector_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTINYSTL_VECTOR_TEST_H_ 2 | #define MYTINYSTL_VECTOR_TEST_H_ 3 | 4 | // vector test : 测试 vector 的接口与 push_back 的性能 5 | 6 | #include 7 | 8 | #include "../MyTinySTL/vector.h" 9 | #include "test.h" 10 | 11 | namespace mystl 12 | { 13 | namespace test 14 | { 15 | namespace vector_test 16 | { 17 | 18 | void vector_test() 19 | { 20 | std::cout << "[===============================================================]\n"; 21 | std::cout << "[----------------- Run container test : vector -----------------]\n"; 22 | std::cout << "[-------------------------- API test ---------------------------]\n"; 23 | int a[] = { 1,2,3,4,5 }; 24 | mystl::vector v1; 25 | mystl::vector v2(10); 26 | mystl::vector v3(10, 1); 27 | mystl::vector v4(a, a + 5); 28 | mystl::vector v5(v2); 29 | mystl::vector v6(std::move(v2)); 30 | mystl::vector v7{ 1,2,3,4,5,6,7,8,9 }; 31 | mystl::vector v8, v9, v10; 32 | v8 = v3; 33 | v9 = std::move(v3); 34 | v10 = { 1,2,3,4,5,6,7,8,9 }; 35 | 36 | FUN_AFTER(v1, v1.assign(8, 8)); 37 | FUN_AFTER(v1, v1.assign(a, a + 5)); 38 | FUN_AFTER(v1, v1.emplace(v1.begin(), 0)); 39 | FUN_AFTER(v1, v1.emplace_back(6)); 40 | FUN_AFTER(v1, v1.push_back(6)); 41 | FUN_AFTER(v1, v1.insert(v1.end(), 7)); 42 | FUN_AFTER(v1, v1.insert(v1.begin() + 3, 2, 3)); 43 | FUN_AFTER(v1, v1.insert(v1.begin(), a, a + 5)); 44 | FUN_AFTER(v1, v1.pop_back()); 45 | FUN_AFTER(v1, v1.erase(v1.begin())); 46 | FUN_AFTER(v1, v1.erase(v1.begin(), v1.begin() + 2)); 47 | FUN_AFTER(v1, v1.reverse()); 48 | FUN_AFTER(v1, v1.swap(v4)); 49 | FUN_VALUE(*v1.begin()); 50 | FUN_VALUE(*(v1.end() - 1)); 51 | FUN_VALUE(*v1.rbegin()); 52 | FUN_VALUE(*(v1.rend() - 1)); 53 | FUN_VALUE(v1.front()); 54 | FUN_VALUE(v1.back()); 55 | FUN_VALUE(v1[0]); 56 | FUN_VALUE(v1.at(1)); 57 | int* p = v1.data(); 58 | *p = 10; 59 | *++p = 20; 60 | p[1] = 30; 61 | std::cout << " After change v1.data() :" << "\n"; 62 | COUT(v1); 63 | std::cout << std::boolalpha; 64 | FUN_VALUE(v1.empty()); 65 | std::cout << std::noboolalpha; 66 | FUN_VALUE(v1.size()); 67 | FUN_VALUE(v1.max_size()); 68 | FUN_VALUE(v1.capacity()); 69 | FUN_AFTER(v1, v1.resize(10)); 70 | FUN_VALUE(v1.size()); 71 | FUN_VALUE(v1.capacity()); 72 | FUN_AFTER(v1, v1.shrink_to_fit()); 73 | FUN_VALUE(v1.size()); 74 | FUN_VALUE(v1.capacity()); 75 | FUN_AFTER(v1, v1.resize(6, 6)); 76 | FUN_VALUE(v1.size()); 77 | FUN_VALUE(v1.capacity()); 78 | FUN_AFTER(v1, v1.shrink_to_fit()); 79 | FUN_VALUE(v1.size()); 80 | FUN_VALUE(v1.capacity()); 81 | FUN_AFTER(v1, v1.clear()); 82 | FUN_VALUE(v1.size()); 83 | FUN_VALUE(v1.capacity()); 84 | FUN_AFTER(v1, v1.reserve(5)); 85 | FUN_VALUE(v1.size()); 86 | FUN_VALUE(v1.capacity()); 87 | FUN_AFTER(v1, v1.reserve(20)); 88 | FUN_VALUE(v1.size()); 89 | FUN_VALUE(v1.capacity()); 90 | FUN_AFTER(v1, v1.shrink_to_fit()); 91 | FUN_VALUE(v1.size()); 92 | FUN_VALUE(v1.capacity()); 93 | PASSED; 94 | #if PERFORMANCE_TEST_ON 95 | std::cout << "[--------------------- Performance Testing ---------------------]\n"; 96 | std::cout << "|---------------------|-------------|-------------|-------------|\n"; 97 | std::cout << "| push_back |"; 98 | #if LARGER_TEST_DATA_ON 99 | CON_TEST_P1(vector, push_back, rand(), SCALE_LL(LEN1), SCALE_LL(LEN2), SCALE_LL(LEN3)); 100 | #else 101 | CON_TEST_P1(vector, push_back, rand(), SCALE_L(LEN1), SCALE_L(LEN2), SCALE_L(LEN3)); 102 | #endif 103 | std::cout << "\n"; 104 | std::cout << "|---------------------|-------------|-------------|-------------|\n"; 105 | PASSED; 106 | #endif 107 | std::cout << "[----------------- End container test : vector -----------------]\n"; 108 | } 109 | 110 | } // namespace vector_test 111 | } // namespace test 112 | } // namespace mystl 113 | #endif // !MYTINYSTL_VECTOR_TEST_H_ 114 | 115 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 2.0.1{build} 2 | 3 | branches: 4 | only: 5 | - master 6 | 7 | image: 8 | - Visual Studio 2015 9 | - Visual Studio 2017 10 | 11 | configuration: 12 | - Release 13 | 14 | build: 15 | parallel: true 16 | project: MSVC\MyTinySTL_VS2015.sln 17 | 18 | test_script: 19 | - cmd: cd .\MSVC\x64\Release\ 20 | - cmd: MyTinySTL.exe 21 | 22 | --------------------------------------------------------------------------------