Skip to content

Commit b62ac19

Browse files
committed
Version 0.3 update
1 parent cf6f83f commit b62ac19

16 files changed

+47
-63
lines changed

book.tex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@
3333
\frontmatter
3434
\input{chapters/00_title_page}
3535

36-
%\input{chapters/01_preface} % Reviewed
36+
\input{chapters/01_preface} % Reviewed
3737

3838
\mainmatter
3939
\tableofcontents
4040

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
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
4444

4545
\input{chapters/90_theory} % TODO
4646

chapters/02_introduction.tex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ \section{A simpler mental model for iterators}
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

147+
\newpage
148+
147149
In some cases, a single returned iterator denotes multiple ranges.
148150

149151
\begin{box-note}

chapters/03_algorithms_02_swaps.tex

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
11
\section{Swaps}
22

3-
Before discussing swaps, we need to make a short detour and discuss argument-dependent lookup, an essential aspect of the pre-C++20 version of the std::swap algorithm.
4-
5-
Argument-dependent lookup is relied upon heavily in C++, notably when overloading operators.
6-
7-
\begin{box-note}
8-
\footnotesize Example of argument-dependent lookup for \cpp{operator<<} implemented as a function.
9-
\tcblower
10-
\cppfile{code_examples/theory/adl_code.h}
11-
\end{box-note}
12-
13-
The situation changes slightly when the function is implemented as a friend function. Such a function is a member of the surrounding namespace. However, it is not visible outside of ADL.
14-
15-
\begin{box-note}
16-
\footnotesize Example of argument-dependent lookup for \cpp{operator<<} implemented as a friend function.
17-
\tcblower
18-
\cppfile{code_examples/theory/adl_friend_code.h}
19-
\end{box-note}
20-
21-
The benefit of relying on ADL is that there is no complexity on the caller's site. An unqualified call will invoke the correct overload. Except, this wouldn't be C++ if there weren't an exception to this rule.
22-
23-
If on top of having the ability to specialize, we also want default behaviour as a fallback, the caller now needs to make sure to pull in the default overload to the local scope.
24-
25-
\begin{box-note}
26-
\footnotesize Example of argument-dependent lookup with a default templated version of the function.
27-
\tcblower
28-
\cppfile{code_examples/theory/adl_default_code.h}
29-
\end{box-note}
3+
Before C++11 and the introduction of move operations, swaps were the only way objects with value semantics could exchange content without involving a deep copy.
304

315
\subsection{\texorpdfstring{\cpp{std::swap}}{\texttt{std::swap}}}
326
\index{\cpp{std::swap}}
@@ -35,7 +9,7 @@ \subsection{\texorpdfstring{\cpp{std::swap}}{\texttt{std::swap}}}
359

3610
\cppversions{\texttt{swap}}{\CC98}{\CC20}{N/A}{\CC20}
3711

38-
Correctly calling swap (as mentioned at the beginning of this section) requires pulling the default std::swap version to the local scope.
12+
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}).
3913

4014
\begin{box-note}
4115
\footnotesize Example of correctly calling \cpp{std::swap}.

chapters/03_algorithms_03_sorting.tex

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ \section{Sorting}
3535
\subsection{\texorpdfstring{\cpp{std::lexicographical_compare}}{\texttt{std::lexicographical\_compare}}}
3636
\index{\cpp{std::lexicographical_compare}}
3737

38-
Lexicographical \texttt{strict\_weak\_ordering} for ranges is exposed through the \texttt{std::lexicographical\_compare} algorithm.
38+
Lexicographical \texttt{strict\_weak\_ordering} for ranges is exposed through the \newline\texttt{std::lexicographical\_compare} algorithm.
3939

4040
\cppversions{\texttt{lex\dots compare}}{\CC98}{\CC20}{\CC17}{\CC20}
4141

@@ -58,7 +58,14 @@ \subsection{\texorpdfstring{\cpp{std::lexicographical_compare}}{\texttt{std::lex
5858
\subsection{\texorpdfstring{\cpp{std::lexicographical_compare_three_way}}{\texttt{std::lexicographical\_compare\_three\_way}}}
5959
\index{\cpp{std::lexicographical_compare_three_way}}
6060

61-
The \texttt{std::lexicographical\_compare\_three\_way} is the spaceship operator equivalent to \texttt{std::lexicographical\_compare}. It returns one of \texttt{std::strong\_ordering}, \texttt{std::weak\_ordering} or \texttt{std::partial\_ordering} types, depending on the type returned by the elements' spaceship operator.
61+
The \texttt{std::lexicographical\_compare\_three\_way} is the spaceship operator equivalent to \texttt{std::lexicographical\_compare}. It returns one of:
62+
\begin{itemize}
63+
\item\texttt{std::strong\_ordering}
64+
\item \texttt{std::weak\_ordering}
65+
\item \texttt{std::partial\_ordering}
66+
\end{itemize}
67+
68+
The type depends on the type returned by the elements' spaceship operator.
6269

6370
\cppversions{\texttt{lex\dots three\_way}}{\CC20}{\CC20}{N/A}{N/A}
6471
\constraints{\texttt{(input\_range, input\_range)}}{}{\texttt{operator<=>}}{\texttt{strong\_ordering}, \texttt{weak\_ordering}, \texttt{partial\_ordering}}
@@ -140,7 +147,7 @@ \subsection{\texorpdfstring{\cpp{std::is_sorted_until}}{\texttt{std::is\_sorted\
140147
\end{box-note}
141148

142149
Note that because of the behaviour of \cpp{std::is_sorted_until}, the following is always true:\\
143-
\small\cpp{std::is_sorted(r.begin(), std::is_sorted_until(r.begin(), r.end()))}
150+
\begin{small}\cpp{std::is_sorted(r.begin(), std::is_sorted_until(r.begin(), r.end()))}\end{small}
144151

145152
\subsection{\texorpdfstring{\cpp{std::partial_sort}}{\texttt{std::partial\_sort}}}
146153
\index{\cpp{std::partial_sort}}
@@ -188,8 +195,8 @@ \subsection{\texorpdfstring{\cpp{qsort}}{\texttt{qsort}} - C standard library}
188195

189196
I would strongly recommend avoiding \cpp{qsort}, as \cpp{std::sort} and \cpp{std::ranges::sort} should be a better choice in every situation. Moreover, \cpp{qsort} is only valid for trivially copyable types, and those will correctly optimize to \cpp{memcpy}/\cpp{memmove} operations even when using \cpp{std::sort}.
190197

191-
\begin{box-note}
198+
\begin{box-nobreak}
192199
\footnotesize Example of using \cpp{std::sort} to achieve the same result as in the previous example.
193200
\tcblower
194201
\cppfile{code_examples/algorithms/qsort_not_code.h}
195-
\end{box-note}
202+
\end{box-nobreak}

chapters/03_algorithms_04_partitioning.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ \subsection{\texorpdfstring{\cpp{std::is_partitioned}}{\texttt{std::is\_partitio
4545

4646
Note that a sorted range is always partitioned for any possible value (with a different partition point).
4747

48-
\begin{box-note}
48+
\begin{box-nobreak}
4949
\footnotesize Example of using \cpp{std::is_partitioned}.
5050
\tcblower
5151
\cppfile{code_examples/algorithms/is_partitioned_code.h}
52-
\end{box-note}
52+
\end{box-nobreak}
5353

5454
\subsection{\texorpdfstring{\cpp{std::partition_copy}}{\texttt{std::partition\_copy}}}
5555
\index{\cpp{std::partition_copy}}

chapters/03_algorithms_05_divide.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ \subsection{\texorpdfstring{\cpp{std::equal_range}}{\texttt{std::equal\_range}}}
5757
\subsection{\texorpdfstring{\cpp{std::partition_point}}{\texttt{std::partition\_point}}}
5858
\index{\cpp{std::partition_point}}
5959

60-
Despite the naming, \cpp{std:partition_point} works very similarly to \cpp{std::upper_bound}, however instead of searching for a particular value, it searches using a predicate.
60+
Despite the naming, \cpp{std:partition_point} works very similarly to \texttt{std::upper\-\_bound}, however instead of searching for a particular value, it searches using a predicate.
6161

6262
\cppversions{\texttt{partition\_point}}{\CC11}{\CC20}{N/A}{\CC20}
6363
\constraints{\texttt{forward\_range}}{}{N/A}{\texttt{unary\_predicate}}

chapters/03_algorithms_07_sets.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ \subsection{\texorpdfstring{\cpp{std::set_symmetric_difference}}{\texttt{std::se
3434

3535
For equivalent elements, where the first range contains $M$ such elements and the second range contains $N$ such elements, the result will contain the last \cpp{std::abs(M-N)} such elements from the corresponding range. That is, if $M>N$, $M-N$ elements will be copied from the first range; otherwise, $N-M$ elements will be copied from the second range.
3636

37-
\begin{box-note}
37+
\begin{box-nobreak}
3838
\footnotesize Example of using \cpp{std::set_symmetric_difference}.
3939
\tcblower
4040
\cppfile{code_examples/algorithms/set_symmetric_difference_code.h}
41-
\end{box-note}
41+
\end{box-nobreak}
4242

4343
\begin{box-note}
4444
\footnotesize Example demonstrating \cpp{std::set_symmetric_difference} behaviour when equivalent elements are present.

chapters/03_algorithms_08_transformations.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ \subsection{\texorpdfstring{\cpp{std::reverse}}{\texttt{std::reverse}}}
9393
\cppfile{code_examples/algorithms/reverse_code.h}
9494
\end{box-note}
9595

96-
C-style arrays and C-style strings can be adapted using \cpp{std::span} and \cpp{std::string_view} to allow reverse iteration.
96+
C-style arrays and C-style strings can be adapted using \cpp{std::span} and \texttt{std::string\-\_view} to allow reverse iteration.
9797

9898
\begin{box-note}
9999
\footnotesize Example of using \cpp{std::span} and \cpp{std::string_view} to addapt C-style constructs for reverse iteration.
@@ -104,7 +104,7 @@ \subsection{\texorpdfstring{\cpp{std::reverse}}{\texttt{std::reverse}}}
104104
\subsection{\texorpdfstring{\cpp{std::rotate}}{\texttt{std::rotate}}}
105105
\index{\cpp{std::rotate}}
106106

107-
The \cpp{std::rotate} algorithm rearranges elements in the range from \cpp{[first, middle),[middle, last)} to \cpp{[middle, last),[first, middle)}.
107+
The \cpp{std::rotate} algorithm rearranges elements in the range from \texttt{[first, middle),} \texttt{[middle, last)} to \texttt{[middle, last),} \texttt{[first, middle)}.
108108

109109
\cppversions{\texttt{rotate}}{\CC11}{\CC20}{\CC17}{\CC20}
110110
\constraints{\texttt{(forward\_range, forward\_iterator)}}{\texttt{(forward\_range, forward\_iterator)}}{}{}
@@ -118,7 +118,7 @@ \subsection{\texorpdfstring{\cpp{std::rotate}}{\texttt{std::rotate}}}
118118
\subsection{\texorpdfstring{\cpp{std::shuffle}}{\texttt{std::shuffle}}}
119119
\index{\cpp{std::shuffle}}
120120

121-
The \cpp{std::shuffle} algorithm is a successor of the now-defunct \cpp{std::random_shuffle} algorithm (deprecated in \CC14, removed in \CC17) and relies on new random facilities added in \CC11.
121+
The \cpp{std::shuffle} algorithm is a successor of the now-defunct (deprecated in \CC14, removed in \CC17) \cpp{std::random_shuffle} algorithm and relies on new random facilities added in \CC11.
122122

123123
\cppversions{\texttt{shuffle}}{\CC11}{N/A}{N/A}{\CC20}
124124
\constraints{\texttt{random\_access\_range}}{}{}{}

chapters/03_algorithms_10_general_reductions.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ \subsection{\texorpdfstring{\cpp{std::reduce}}{\texttt{std::reduce}}}
1414
\cppversions{\texttt{reduce}}{\CC17}{\CC20}{\CC17}{N/A}
1515
\constraints{\texttt{input\_range}}{\texttt{forward\_range}}{\texttt{std::plus<>()}}{\texttt{binary\_functor}}
1616

17-
Note that while we have access to a sequenced execution policy (\cpp{std::execution::seq}), this does not make \cpp{std::reduce} sequenced in a left-fold sense.
17+
Note that while we have access to a sequenced execution policy (i.e. \newline\cpp{std::execution::seq}), this does not make \cpp{std::reduce} sequenced in a left-fold sense.
1818

1919
\begin{box-note}
2020
\footnotesize Example of using \cpp{std::reduce} with and without an execution policy.
@@ -35,7 +35,7 @@ \subsection{\texorpdfstring{\cpp{std::reduce}}{\texttt{std::reduce}}}
3535
\subsection{\texorpdfstring{\cpp{std::transform_reduce}}{\texttt{std::transform\_reduce}}}
3636
\index{\cpp{std::transform_reduce}}
3737

38-
The \cpp{std::transform_reduce} algorithm is the generalised counterpart to \cpp{std::inner_product}. On top of the two-range variant, the algorithm also provides a unary overload.
38+
The \cpp{std::transform_reduce} algorithm is the generalised counterpart to \texttt{std::inner\-\_product}. On top of the two-range variant, the algorithm also provides a unary overload.
3939

4040
\cppversions{\texttt{transform\_reduce}}{\CC17}{\CC20}{\CC17}{N/A}
4141
\constraints{\texttt{input\_range}}{\texttt{forward\_range}}{N/A}{\texttt{(binary\_functor, unary\_functor)}}

chapters/03_algorithms_12_generators.tex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ \subsection{\texorpdfstring{\cpp{std::iota}}{\texttt{std::iota}}}
5050
\cppfile{code_examples/algorithms/iota_code.h}
5151
\end{box-note}
5252

53-
Notably, the \cpp{std::iota} algorithm is also an outlier in the support added with the C++20 standard. The std::iota algorithm did not receive a range version. However, we do have access to an iota view.
53+
Notably, the \cpp{std::iota} algorithm is also an outlier in the support added with the C++20 standard. The \cpp{std::iota} algorithm did not receive a range version. However, we do have access to an iota view.
5454

55-
\begin{box-note}
55+
\begin{box-nobreak}
5656
\footnotesize Example of using both finite and infinite \cpp{std::views::iota}.
5757
\tcblower
5858
\cppfile{code_examples/algorithms/iota_view_code.h}
59-
\end{box-note}
59+
\end{box-nobreak}
6060

61-
Here we take advantage of the finite view constructor \cpp{std::views::iota(1,10)} to establish the output size (line 3), which allows us to use the infinite view \cpp{std::views::iota(5)} for the second parameter. Functionally, we could swap even the second view for a finite one. However, this would impose an additional (and unnecessary) boundary check.
61+
Here we take advantage of the finite view constructor \cpp{std::views::iota(1,10)} to establish the output size (line 3), which allows us to use the infinite view \texttt{std::views\-::iota(5)} for the second parameter. Functionally, we could swap even the second view for a finite one. However, this would impose an additional (and unnecessary) boundary check.

0 commit comments

Comments
 (0)