Skip to content

Commit 6b18572

Browse files
committed
Version 1.0.0 update.
1 parent db75fb4 commit 6b18572

File tree

141 files changed

+1230
-1054
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+1230
-1054
lines changed

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(c) RNDr. Šimon Tóth 2022 (business@simontoth.eu)
1+
(c) RNDr. Šimon Tóth 2022-2023 (business@simontoth.eu)
22

33
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License
44

book.tex

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,21 @@
1-
%\documentclass[10pt,b5paper,svgnames,table,twoside]{memoir}
2-
%\documentclass[11pt,a4paper,svgnames,table,twoside]{memoir}
31
\documentclass[11pt,svgnames,table,a4paper]{book}
4-
%\usepackage{showframe}
5-
%\checkandfixthelayout
6-
7-
\newcommand{\version}{0.3.0}
8-
\usepackage{hyperref}
9-
\hypersetup{
10-
colorlinks=true,
11-
linkcolor=blue,
12-
filecolor=magenta,
13-
urlcolor=cyan,
14-
pdftitle={Standard C++ Algorithms},
15-
pdfpagemode=FullScreen,
16-
}
17-
\usepackage{enumitem}
18-
\newcommand*\circled[1]{\tikz[baseline=(char.base)]{
19-
\node[shape=circle,draw,inner sep=1pt] (char) {#1};}}
20-
21-
\input{packages/fonts}
22-
\input{packages/color_blocks}
23-
\input{packages/code_blocks}
24-
\input{packages/glossary_and_index}
25-
\input{packages/local}
26-
27-
\title{The 114 C++ standard algorithms\\and other related topics}
28-
29-
\author{RNDr. Šimon Tóth}
30-
\date{2022}
2+
\input{packages/packages}
313

324
\begin{document}
335
\frontmatter
346
\input{chapters/00_title_page}
35-
36-
\input{chapters/01_preface} % Reviewed
7+
\input{chapters/01_preface}
378

389
\mainmatter
3910
\tableofcontents
40-
41-
\input{chapters/02_introduction} % In review
42-
\input{chapters/03_algorithms_00_main} % In review
43-
\input{chapters/04_ranges_in_depth} % In review
44-
45-
\input{chapters/90_theory} % TODO
11+
12+
\input{chapters/02_introduction}
13+
\input{chapters/03_algorithms_00_main}
14+
\input{chapters/04_views_00_main}
15+
\input{chapters/90_theory}
4616

4717
\appendix
48-
\input{chapters/XX_index}
49-
50-
% Section on iterator invalidation
18+
\printindex
5119

5220
\backmatter
5321

chapters/00_title_page.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
\parindent 0pt
2424
\parskip \baselineskip
2525
\vfill
26-
\textcopyright{} 2022 Šimon Tóth \\
26+
\textcopyright{} 2022-2023 Šimon Tóth \\
2727
All rights reserved.
2828

2929
This work may be distributed and/or modified under the conditions of the CC-BY-NC-SA license.

chapters/01_preface.tex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,16 @@ \section*{Why cc-by-sa-nc}
3030

3131
Explicitly, any personal use is permitted. For example, you can read, print, or share the book with your friends.
3232

33-
If you want to use this content where you are unsure whether you fit within the Creative Commons commercial definition\footnote{primarily intended for or directed toward commercial advantage or monetary compensation}, feel free to contact me on \href{https://twitter.com/SimonToth83}{Twitter}, \href{https://cz.linkedin.com/in/simontoth}{LinkedIn} or by \href{mailto:business@simontoth.eu}{email} (my DMs are always open).
33+
If you want to use this content where you are unsure whether you fit within the Creative Commons commercial definition\footnote{primarily intended for or directed toward commercial advantage or monetary compensation}, feel free to contact me on \href{https://hachyderm.io/@simontoth}{Mastodon}, \href{https://cz.linkedin.com/in/simontoth}{LinkedIn} or by \href{mailto:business@simontoth.eu}{email} (my DMs are always open).
3434

3535
\section*{Book status}
3636

37-
The book is currently in pre-release.
37+
This book is currently content-complete (upto and including \CC20).
3838

39-
To keep up with the changes, visit the hosting repository: \url{https://github.com/HappyCerberus/book-cpp-algorithms}. Internal changelog will be kept after version 1.0 is released.
39+
To keep up with the changes, visit the hosting repository: \url{https://github.com/HappyCerberus/book-cpp-algorithms}.
40+
41+
\subsection*{Changelog}
42+
43+
\begin{enumerate}
44+
\item[1.0] First complete release
45+
\end{enumerate}

chapters/02_introduction.tex

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,33 @@ \section{History of standard \texorpdfstring{\CC}{C++} algorithms}
1111
The \CC98 standard introduced most of the algorithms. However, it was the \CC11 standard with its introduction of lambdas that made algorithms worthwhile. Before lambdas, the time investment of writing a custom function object made the usefulness of algorithms dubious.
1212

1313
\raggedbottom
14-
\begin{box-nobreak}
14+
\begin{codebox}[]{\href{https://godbolt.org/z/73r9n1WYM}{\ExternalLink}}
1515
\footnotesize Example of \cpp{std::for_each}\index{\cpp{std::for_each}} algorithm with a custom function object, calculating the number of elements and their sum.
1616
\tcblower
1717
\cppfile{code_examples/introduction/history_cc98_code.h}
18-
\end{box-nobreak}
18+
\end{codebox}
1919

20-
\begin{box-note}
20+
\begin{codebox}[]{\href{https://godbolt.org/z/zv4fWbT3z}{\ExternalLink}}
2121
\footnotesize Example of \cpp{std::for_each}\index{\cpp{std::for_each}} algorithm with a capturing lambda, calculating the number of elements and their sum.
2222
\tcblower
2323
\cppfile{code_examples/introduction/history_cc11_code.h}
24-
\end{box-note}
24+
\end{codebox}
2525

2626
The \CC17 standard introduced parallel algorithms that provide an easy way to speed up processing with minimal effort. All you need to do is to specify the desired execution model, and the library will take care of parallelizing the execution.
2727

28-
\begin{box-note}
28+
\begin{codebox}[]{\href{https://godbolt.org/z/1nK5944K7}{\ExternalLink}}
2929
\footnotesize Example of \cpp{std::for_each}\index{\cpp{std::for_each}} algorithm using unsequenced parallel execution model. Note that counters are now shared state and need to be \cpp{std::atomic}\index{\cpp{std::atomic}} or protected by a \cpp{std::mutex}\index{\cpp{std::mutex}}.
3030
\tcblower
3131
\cppfile{code_examples/introduction/history_cc17_code.h}
32-
\end{box-note}
32+
\end{codebox}
3333

3434
Finally, the \CC20 standard introduced a significant re-design in the form of ranges and views. Range versions of algorithms can now operate on ranges instead of \cpp{begin} and \cpp{end} iterators and views provide lazily evaluated versions of algorithms and utilities.
3535

36-
\begin{box-note}
36+
\begin{codebox}[]{\href{https://godbolt.org/z/57TGnzzxc}{\ExternalLink}}
3737
\footnotesize Example of the range version of the \cpp{std::for_each}\index{\cpp{std::for_each}} algorithm.
3838
\tcblower
3939
\cppfile{code_examples/introduction/history_cc20_code.h}
40-
\end{box-note}
40+
\end{codebox}
4141

4242
As of the time of writing, the \CC23 standard is not finalized. However, we already know that it will introduce more range algorithms, more views and the ability to implement custom views.
4343

@@ -51,19 +51,19 @@ \section{Iterators and ranges}
5151

5252
To reference the entire content of a data structure, we can use the \cpp{begin()} and \cpp{end()} methods that return an iterator to the first element and an iterator one past the last element, respectively. Hence, the range \cpp{[begin, end)} contains all data structure elements.
5353

54-
\begin{box-note}
54+
\begin{codebox}[]{\href{https://godbolt.org/z/Wj4YjE51v}{\ExternalLink}}
5555
\footnotesize Example of specifying a range using two iterators.
5656
\tcblower
5757
\cppfile{code_examples/introduction/iterators_code.h}
58-
\end{box-note}
58+
\end{codebox}
5959

6060
Sentinels follow the same idea. However, they do not need to be of an iterator type. Instead, they only need to be comparable to an iterator. The exclusive end of the range is then the first iterator that compares equal to the sentinel.
6161

62-
\begin{box-note}
62+
\begin{codebox}[]{\href{https://godbolt.org/z/qKrMo7scn}{\ExternalLink}}
6363
\footnotesize Example of specifying a range using an iterator and custom sentinel. The sentinel will compare \cpp{true} with iterators at least the given distance from the start iterator, therefore defining a range with the specified number of elements.
6464
\tcblower
6565
\cppfile{code_examples/introduction/sentinels_code.h}
66-
\end{box-note}
66+
\end{codebox}
6767

6868
\subsection{Iterator categories}
6969

@@ -82,11 +82,11 @@ \subsection{Iterator categories}
8282
\textit{arrays, e.g. std::vector}\index{\cpp{std::vector}}
8383
\end{description}
8484

85-
\begin{box-note}
85+
\begin{codebox}[]{\href{https://godbolt.org/z/dcaMEdnoM}{\ExternalLink}}
8686
\footnotesize Example demonstrating the difference between a random access iterator provided by \cpp{std::vector} and a bidirectional iterator provided by \cpp{std::list}.
8787
\tcblower
8888
\cppfile{code_examples/introduction/categories_code.h}
89-
\end{box-note}
89+
\end{codebox}
9090

9191
\subsection{Range categories}
9292

@@ -128,36 +128,36 @@ \section{A simpler mental model for iterators}
128128

129129
Ranges passed in as arguments are usually apparent, typically specified by pair of iterators.
130130

131-
\begin{box-note}
131+
\begin{codebox}[]{\href{https://godbolt.org/z/zTh9rn5E4}{\ExternalLink}}
132132
\footnotesize Example with two ranges passed in as an argument. The input range is fully specified, and the end iterator for the output range is implied from the number of elements in the input range.
133133
\tcblower
134134
\cppfile{code_examples/introduction/mental_range_code.h}
135-
\end{box-note}
135+
\end{codebox}
136136

137137
The returned range can also be evident from the semantics of the algorithm.
138138

139-
\begin{box-note}
139+
\begin{codebox}[]{\href{https://godbolt.org/z/escqfWsnE}{\ExternalLink}}
140140
\footnotesize Example of \cpp{std::is_sorted_until} that returns an iterator to the first out-of-order element, which can also be thought as the end iterator for a maximal sorted sub-range.
141141
\tcblower
142142
\cppfile{code_examples/introduction/mental_sorted_code.h}
143-
\end{box-note}
143+
\end{codebox}
144144

145145
The benefit of thinking about the returned value as the end iterator of a range is that it removes the potential for corner cases. For example, what if the algorithm doesn't find any element out of order? The returned value will be the end iterator of the source range, meaning that the range returned is simply the entire source range.
146146

147147
\newpage
148148

149149
In some cases, a single returned iterator denotes multiple ranges.
150150

151-
\begin{box-note}
151+
\begin{codebox}[]{\href{https://godbolt.org/z/YEGKPToz7}{\ExternalLink}}
152152
\footnotesize Example of \cpp{std::lower_bound} that splits the range into two sub-ranges.
153153
\tcblower
154154
\cppfile{code_examples/introduction/mental_two_code.h}
155-
\end{box-note}
155+
\end{codebox}
156156

157157
Even when the algorithm returns an iterator to a specific element, it might be worth considering the implied range.
158158

159-
\begin{box-note}
159+
\begin{codebox}[]{\href{https://godbolt.org/z/Er15W6K5W}{\ExternalLink}}
160160
\footnotesize Example of \cpp{std::find} establishing a prefix range that doesn't contain the searched-for element.
161161
\tcblower
162162
\cppfile{code_examples/introduction/mental_find_code.h}
163-
\end{box-note}
163+
\end{codebox}

chapters/03_algorithms_01_foreach.tex

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
\section{Introducing the algorithms}
22

3-
In this chapter, we introduce each of the 114 standard algorithms. The groups of algorithms are arbitrary and mainly introduced for presentation clarity. Therefore, you might correctly argue that a specific algorithm would be better suited to reside in a different group.
3+
In this chapter, we introduce each of the standard algorithms. The groups of algorithms are arbitrary and mainly introduced for presentation clarity. Therefore, you might correctly argue that a specific algorithm would be better suited to reside in a different group.
44

55
Before we start, we will use the \cpp{std::for_each} and \cpp{std::for_each_n} algorithms to demonstrate this chapter's structure for each algorithm.
66

@@ -38,35 +38,35 @@ \subsection{\texorpdfstring{\cpp{std::for_each}}{\texttt{std::for\_each}}}
3838

3939
\circled{4} The C++11 standard introduced the range-based for loop, which mostly replaced the uses of \cpp{std::for_each}.
4040

41-
\begin{box-note}
41+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/b6qEoonno}{\ExternalLink}}
4242
\footnotesize Example of a range loop over all elements of a \cpp{std::vector}.
4343
\tcblower
4444
\cppfile{code_examples/algorithms/for_each_code_range.h}
45-
\end{box-note}
45+
\end{codebox}
4646

47-
\begin{box-note}
47+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/M38M379To}{\ExternalLink}}
4848
\footnotesize Example of a \cpp{std::for_each} loop over all elements of a \cpp{std::vector}.
4949
\tcblower
5050
\cppfile{code_examples/algorithms/for_each_code_simple.h}
51-
\end{box-note}
51+
\end{codebox}
5252

5353
However, there are still a few corner cases when using \cpp{std::for_each} is preferable.
5454

5555
The first case is straightforward parallelization. Invoking an expensive operation for each element in parallel is trivial with \cpp{std::for_each}. As long as the operations are independent, there is no need for synchronization primitives.
5656

57-
\begin{box-note}
57+
\begin{codebox}[breakable]{\href{https://compiler-explorer.com/z/3bq4xT3G9}{\ExternalLink}}
5858
\footnotesize Example of a parallel \cpp{std::for_each} invoking a method on each element independently in parallel.
5959
\tcblower
6060
\cppfile{code_examples/algorithms/for_each_code_parallel.h}
61-
\end{box-note}
61+
\end{codebox}
6262

6363
Second, the range version can provide a more concise and explicit syntax in some cases because of the projection support introduced in C++20.
6464

65-
\begin{box-note}
65+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/sfxWa4T5f}{\ExternalLink}}
6666
\footnotesize Example of the range version of \cpp{std::ranges::for_each} utilizing a projection to invoke the method \cpp{getValue()} (line 13) on each element and summing the resulting values using a lambda (line 12).
6767
\tcblower
6868
\cppfile{code_examples/algorithms/for_each_code_cpp20.h}
69-
\end{box-note}
69+
\end{codebox}
7070

7171
\subsection{\texorpdfstring{\cpp{std::for_each_n}}{\texttt{std::for\_each\_n}}}
7272
\index{\cpp{std::for_each_n}}
@@ -95,10 +95,12 @@ \subsection{\texorpdfstring{\cpp{std::for_each_n}}{\texttt{std::for\_each\_n}}}
9595

9696
\circled{4} While \cpp{std::for_each} operates on the entire range, the interval $[begin, end)$, \cpp{std::for_each_n} operates on the range $[first, first+n)$. Importantly, because the algorithm does not have access to the end iterator of the source range, it does no out-of-bounds checking, and it is the responsibility of the caller to ensure that the range $[first, first+n)$ is valid.
9797

98-
\begin{box-note}
98+
\raggedbottom
99+
100+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/1hfje76Yq}{\ExternalLink}}
99101
\footnotesize Example demonstrating multiple uses of \cpp{std::for_each_n}.
100102
\tcblower
101103
\cppfile{code_examples/algorithms/for_each_n_code.h}
102-
\end{box-note}
104+
\end{codebox}
103105

104106
Sending invitations to the \texttt{MAIN\_SEATS} top players is done in parallel (lines 4-7). Then all users' scores are stored in chunks of \texttt{PAGE\_SIZE} records (lines 13-15). Note that calculating the remaining number of elements (line 12) and jumping ahead by the number of stored elements (line 17) requires a random access iterator (in this case, provided by \cpp{std::vector}).

chapters/03_algorithms_02_swaps.tex

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ \subsection{\texorpdfstring{\cpp{std::swap}}{\texttt{std::swap}}}
1111

1212
Correctly calling swap requires pulling the default std::swap version to the local scope. To read more on why this is needed check out the theory chapter of this book, specifically the section on ADL (\ref{theory:adl}).
1313

14-
\begin{box-note}
14+
\begin{codebox}[breakable]{\href{https://compiler-explorer.com/z/Yzvzrb4rY}{\ExternalLink}}
1515
\footnotesize Example of correctly calling \cpp{std::swap}.
1616
\tcblower
1717
\cppfile{code_examples/algorithms/swap_calling_code.h}
18-
\end{box-note}
19-
\newpage
18+
\end{codebox}
2019

2120
The C++20 rangified version of swap removes this complexity, and it will:
2221

@@ -26,11 +25,11 @@ \subsection{\texorpdfstring{\cpp{std::swap}}{\texttt{std::swap}}}
2625
\item if the parameters are also not arrays, it will default to a move-swap
2726
\end{itemize}
2827

29-
\begin{box-note}
28+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/8GxdMxsan}{\ExternalLink}}
3029
\footnotesize Example of specializing and calling \cpp{std::ranges::swap}.
3130
\tcblower
3231
\cppfile{code_examples/algorithms/swap_range_code.h}
33-
\end{box-note}
32+
\end{codebox}
3433

3534
\subsection{\texorpdfstring{\cpp{std::iter_swap}}{\texttt{std::iter\_swap}}}
3635
\index{\cpp{std::iter_swap}}
@@ -41,19 +40,19 @@ \subsection{\texorpdfstring{\cpp{std::iter_swap}}{\texttt{std::iter\_swap}}}
4140

4241
\constraints{(\cpp{forward_iterator}, \cpp{forward_iterator}) (non-range)}{}{}{}
4342

44-
\begin{box-note}
43+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/77enEEh4c}{\ExternalLink}}
4544
\footnotesize Example demonstrating the use \cpp{std::iter_swap} in a generic two-way partition algorithm. The algorithm uses concepts to constrain the acceptable types of its arguments.
4645
\tcblower
4746
\cppfile{code_examples/algorithms/iter_swap_partition_code.h}
48-
\end{box-note}
47+
\end{codebox}
4948

5049
The range version extends the functionality to other dereferenceable objects.
5150

52-
\begin{box-note}
51+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/bxeP3PPaE}{\ExternalLink}}
5352
\footnotesize Example demonstrating the use of range version of \cpp{std::ranges::iter_swap} to swap the values pointed to by two instances of \cpp{std::unique_ptr}.
5453
\tcblower
5554
\cppfile{code_examples/algorithms/iter_swap_unique_ptr_code.h}
56-
\end{box-note}
55+
\end{codebox}
5756

5857
\subsection{\texorpdfstring{\cpp{std::swap_ranges}}{\texttt{std::swap\_ranges}}}
5958
\index{\cpp{std::swap_ranges}}
@@ -62,8 +61,8 @@ \subsection{\texorpdfstring{\cpp{std::swap_ranges}}{\texttt{std::swap\_ranges}}}
6261

6362
\cppversions{\texttt{swap\_ranges}}{\CC98}{\CC20}{\CC17}{\CC20}
6463

65-
\begin{box-note}
64+
\begin{codebox}[]{\href{https://compiler-explorer.com/z/aEPe66f1E}{\ExternalLink}}
6665
\footnotesize Example of swapping the first three elements of an array with the last three elements using \cpp{std::swap_ranges}. Note the reversed order of elements due to the use of \cpp{rbegin}.
6766
\tcblower
6867
\cppfile{code_examples/algorithms/swap_ranges_code.h}
69-
\end{box-note}
68+
\end{codebox}

0 commit comments

Comments
 (0)