├── .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