Skip to content

Commit ed852f5

Browse files
bernhardmgrubersponce
authored andcommitted
Improve More STL slides
1 parent fe28fd4 commit ed852f5

File tree

1 file changed

+53
-25
lines changed

1 file changed

+53
-25
lines changed

talk/morelanguage/morestl.tex

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
\begin{itemize}
4040
\item \mintinline{cpp}{std::vector}, \mintinline{cpp}{std::array}, C arrays, ...
4141
\item not \mintinline{cpp}{std::list} or \mintinline{cpp}{std::deque} (no contiguous storage)
42-
\item \mintinline{cpp}{span} should thus be preferred as function arguments
42+
\item \mintinline{cpp}{span} should thus be preferred as function argument
4343
\end{itemize}
4444
\item Simply a pair (pointer, size), so cheap to copy
4545
\begin{itemize}
@@ -86,27 +86,52 @@
8686

8787
\begin{frame}[fragile]
8888
\frametitlecpp[17]{std::optional}
89-
\begin{block}{Manages an optional contained value}
89+
\begin{block}{Manages an optionally contained value}
9090
\begin{itemize}
91-
\item Contextually converts to bool telling if it contains something
91+
\item Contextually converts to bool, telling if it contains something
9292
\item Has value semantics (Copy, Move, Compare, stack alloc.)
9393
\item Useful for the return value of a function that may fail
9494
\item Useful in place of pointers where value semantics are intuitive
9595
\end{itemize}
9696
\end{block}
97-
\begin{exampleblock}{Code example}
97+
\begin{exampleblock}{}
9898
\small
9999
\begin{cppcode*}{}
100100
std::optional<Phone> parse_phone(std::string_view in) {
101101
if (is_valid_phone(in))
102-
return in; // equiv. to optional<Phone>(in);
103-
else
104-
return {}; // default constructs std::nullopt
102+
return in; // equiv. to optional<Phone>{in};
103+
return {}; // or: return std::nullopt; (empty opt.)
105104
}
106-
auto v = parse_phone(...);
107-
if (v) { // alternatively v.is_valid()
108-
process_phone(v.value()); // *v is equivalent
105+
if (v) { // or: v.is_valid()
106+
process_phone(v.value()); // or: *v (unchecked)
107+
v->call(); // calls Phone::call() (unchecked)
109108
}
109+
v.reset(); assert(!v.has_value()); // or: v = {};
110+
\end{cppcode*}
111+
\end{exampleblock}
112+
\end{frame}
113+
114+
\begin{frame}[fragile]
115+
\frametitlecpp[17]{std::optional}
116+
\begin{exampleblock}{Code example}
117+
\small
118+
\begin{cppcode*}{}
119+
// address may be given for a person or not
120+
void processPerson(std::string_view name,
121+
std::optional<Address> address);
122+
Address addr = wonderland();
123+
processPerson("Alice", std::move(addr));
124+
125+
// Every person has a name, but not always an address
126+
struct Person {
127+
std::string name;
128+
std::optional<Address> address;
129+
};
130+
std::vector<Person> ps = ...;
131+
std::sort(ps.begin(), ps.end(),
132+
[](const Person& a, const Person& b) {
133+
return a.address < b.address;
134+
}); // sorts by address, persons w/o address at front
110135
\end{cppcode*}
111136
\end{exampleblock}
112137
\end{frame}
@@ -124,12 +149,12 @@
124149

125150
\begin{frame}[fragile]
126151
\frametitlecpp[17]{std::variant}
127-
\begin{block}{a type-safe union}
152+
\begin{block}{A type-safe union}
128153
\begin{itemize}
129154
\item Allows the variable to hold any of the given types
130155
\item \mintinline{cpp}{std::get} reads the value of the variant
131156
\item and throws \mintinline{cpp}{std::bad_variant_access} for bad accesses
132-
\item Makes it easy to implement visitor pattern
157+
\item Currently held alternative can be probed
133158
\end{itemize}
134159
\end{block}
135160
\begin{exampleblock}{Code example}
@@ -140,35 +165,38 @@
140165
try {
141166
float val = std::get<float>(opt) // will throw
142167
} catch (std::bad_variant_access const& ex) {...}
143-
144-
// Or check the type before accessing it
145168
if (std::holds_alternative<float>(opt))
146169
std::cout << std::get<float>(opt);
170+
if (const float* v = std::get_if<float>(opt)) { ... }
171+
const int current_alternative = opt.index(); // == 0
147172
\end{cppcode*}
148173
\end{exampleblock}
149174

150175
\end{frame}
151176

152177
\begin{frame}[fragile]
153178
\frametitlecpp[17]{std::variant and the visitor pattern}
154-
\begin{block}{std::visit}
179+
\begin{block}{\texttt{std::visit}}
155180
\begin{itemize}
156-
\item Applies a ``visitor'' to given variant
157-
\item A visitor is a callable able to handle the different types
181+
\item Applies a ``visitor'' to a given variant
182+
\begin{itemize}
183+
\item A visitor is a callable able to handle all different types
184+
\item Must return \mintinline{cpp}{void} or the same type for all overloads
185+
\end{itemize}
158186
\end{itemize}
159187
\end{block}
160188
\begin{exampleblock}{Practically}
161189
\small
162190
\begin{cppcode*}{gobble=2}
163191
struct Visitor {
164-
void operator() (int i) { std::cout << "i32:" << i;}
165-
void operator() (float f) { std::cout << "f32:" << f;}
166-
void operator() (std::string s) { std::cout << s;}
192+
auto operator()(int i) {return "i:"+std::to_string(i);}
193+
auto operator()(float f) {return "f:"+std::to_string(f);}
194+
auto operator()(const std::string& s) { return "s:"+s;}
167195
template <typename T>
168-
void operator() (T t) { return std::cout << "other"; }
196+
auto operator()(const T& t) { return std::string{"?"}; }
169197
};
170198
void print(std::variant<int, float, std::string, char> v) {
171-
std::cout << std::visit(Visitor{}, v) << "\n;
199+
std::cout << std::visit(Visitor{}, v) << '\n';
172200
}
173201
print(100); print(42.0f); print("example"); print('A');
174202
\end{cppcode*}
@@ -220,7 +248,7 @@
220248
\item Allows a variable to hold any type (say bye to \mintinline{cpp}{void*})
221249
\item \mintinline{cpp}{std::any_cast} reads the internal value
222250
\item and throws \mintinline{cpp}{std::bad_any_cast} for bad accesses
223-
\item \mintinline{cpp}{any_cast} will only match concrete types, ignoring inheritance
251+
\item \mintinline{cpp}{std::any_cast} only matches types 1:1, ignoring inheritance
224252
\end{itemize}
225253
\end{block}
226254
\begin{exampleblock}{Code example}
@@ -232,9 +260,9 @@
232260
try {
233261
int val = std::any_cast<int>(val); // will throw
234262
} catch (std::bad_any_cast const& ex) {...}
235-
// Or check the type before accessing it
236-
if (val.type() == typeid(int))
263+
if (val.type() == typeid(int)) // requires RTTI
237264
std::cout << std::any_cast<int>(val);
265+
val.reset(); assert(!val.has_value());
238266
\end{cppcode*}
239267
\end{exampleblock}
240268
\end{frame}

0 commit comments

Comments
 (0)