Skip to content

Commit fe28fd4

Browse files
bernhardmgruberhageboeck
authored andcommitted
Extend slides on templates
Fixes: #283 Co-authored-by: Stephan Hageboeck <[email protected]>
1 parent af26ece commit fe28fd4

File tree

1 file changed

+205
-14
lines changed

1 file changed

+205
-14
lines changed

talk/morelanguage/templates.tex

Lines changed: 205 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
\begin{cppcode}
1515
template<typename T>
1616
const T & max(const T &a, const T &b) {
17-
return a > b ? a : b;
17+
return b < a ? a : b;
1818
}
1919
template<typename T>
2020
struct Vector {
@@ -33,9 +33,10 @@
3333
\item they are compiled for each instantiation
3434
\item they need to be defined before used
3535
\begin{itemize}
36-
\item so all templated code has to be in headers
36+
\item so all template code must typically be in headers
37+
\item or declared to be available externally (\mintinline{cpp}{extern template})
3738
\end{itemize}
38-
\item this may lead to longer compilation times and bigger libraries
39+
\item this may lead to longer compilation times and bigger binaries
3940
\end{itemize}
4041
\end{alertblock}
4142
\newsavebox{\codepiece}
@@ -104,7 +105,7 @@
104105
\end{frame}
105106

106107
\begin{frame}[fragile]
107-
\frametitlecpp[98]{Templates implementation}
108+
\frametitlecpp[98]{Template implementation}
108109
\begin{cppcode*}{}
109110
template<typename KeyType=int, typename ValueType=KeyType>
110111
struct Map {
@@ -131,7 +132,7 @@
131132
\begin{itemize}
132133
\item integral types, pointer, enums in \cpp98
133134
\item \mintinline{cpp}{auto} in \cpp17
134-
\item floats and literal types in \cpp20
135+
\item floating-point and literal types in \cpp20
135136
\end{itemize}
136137
\end{block}
137138
\begin{cppcode*}{}
@@ -145,27 +146,215 @@
145146
\end{frame}
146147

147148
\begin{frame}[fragile]
148-
\frametitlecpp[98]{Templates}
149+
\frametitlecpp[98]{Template specialization}
149150
\begin{block}{Specialization}
150-
templates can be specialized for given values of their parameter
151+
Templates can be specialized for given values of their parameter
151152
\end{block}
153+
\small
152154
\begin{cppcode*}{}
153155
template<typename F, unsigned int N>
154-
struct Polygon {
155-
Polygon(F radius) : m_radius(radius) {}
156-
F perimeter() {return 2*N*sin(PI/N)*m_radius;}
157-
F m_radius;
158-
};
156+
struct Polygon { ... }; // primary template
159157

160-
template<typename F>
158+
template<typename F> // partial specialization
161159
struct Polygon<F, 6> {
162160
Polygon(F radius) : m_radius(radius) {}
163-
F perimeter() {return 6*m_radius;}
161+
F perimeter() { return 6*m_radius; }
164162
F m_radius;
165163
};
164+
template<> // full specialization
165+
struct Polygon<int, 6> {
166+
Polygon(int radius) : m_radius(radius) {}
167+
int perimeter() { return 6*m_radius; }
168+
int m_radius;
169+
};
170+
\end{cppcode*}
171+
\end{frame}
172+
173+
\begin{advanced}
174+
175+
\begin{frame}[fragile]
176+
\frametitlecpp[98]{Template argument deduction}
177+
\begin{block}{Template argument deduction}
178+
\begin{itemize}
179+
\item Template arguments deduced from (function) arguments
180+
\item Template arguments can always be specified explicitly
181+
\item Only for function templates (Before \cpp14)
182+
\end{itemize}
183+
\end{block}
184+
\begin{cppcode*}{}
185+
template <typename T, typename U>
186+
void f(T t, U u) { ... }
187+
188+
f(42, true); // deduces T=int, U=bool
189+
// calls f<int, bool>(42, true);
190+
f<float>(42, true); // sets T=float, deduces U=bool
191+
// calls f<float, bool>(42, true);
192+
// 42 converted to float before call
166193
\end{cppcode*}
167194
\end{frame}
168195

196+
\begin{frame}[fragile]
197+
\frametitlecpp[11]{Template argument deduction}
198+
\begin{block}{Deduced contexts}
199+
\begin{itemize}
200+
\item Compiler can even deduce template arguments inside certain expressions (pattern matching)
201+
\item See \href{https://en.cppreference.com/w/cpp/language/template_argument_deduction}{cppreference} for details
202+
\end{itemize}
203+
\end{block}
204+
\begin{cppcode*}{}
205+
template <typename T>
206+
void f(T* p) { ... }
207+
208+
const int * ip = ...;
209+
f(ip); // deduces T=const int
210+
211+
template <typename T, std::size_t N>
212+
void g(std::array<T*, N> a) { ... }
213+
214+
std::array<int*, 3> aip = ...;
215+
g(aip); // deduces T=int, N=3
216+
\end{cppcode*}
217+
\end{frame}
218+
219+
\begin{frame}[fragile]
220+
\frametitlecpp[11]{Template argument deduction}
221+
\begin{block}{Non-deduced contexts}
222+
\begin{itemize}
223+
\item Deduction from certain expressions is impossible/forbidden
224+
\end{itemize}
225+
\end{block}
226+
\begin{overprint}
227+
\onslide<1>
228+
\begin{alertblock}{}
229+
\footnotesize
230+
\begin{cppcode*}{gobble=2}
231+
template <typename C>
232+
void f(typename C::value_type v) { ... }
233+
f(std::vector<int>{...}); // cannot deduce C
234+
// from a dependent type
235+
template <typename T, std::size_t N>
236+
void g(std::array<T, N * 2> a) { ... }
237+
g(std::array<int, 4>{...}); // deduces T=int,
238+
// cannot deduce N from expression
239+
template <typename T>
240+
void h(std::vector<T> v) { ... }
241+
h({1, 2, 3}); // error, braced-initializer list has no type
242+
h(std::vector<int>{1, 2, 3}); // ok, T=int
243+
\end{cppcode*}
244+
\end{alertblock}
245+
\onslide<2>
246+
\begin{alertblock}{}
247+
\footnotesize
248+
\begin{cppcode*}{gobble=2}
249+
template <typename C, typename F>
250+
void reduce(const C& cont, const F& f = std::plus{});
251+
reduce(std::vector<int>{...}); // error: cannot deduce F
252+
// would need: <typename C, typename F = decltype(std::plus{})>
253+
254+
template<typename T>
255+
const T & max(const T &a, const T &b) { ... }
256+
int i = 3;
257+
max(i, 3.14f); // deduces T=int and T=float, error
258+
// either: max<float>(i, 3.14f);
259+
// or: max(static_cast<float>(i), 3.14f);
260+
\end{cppcode*}
261+
\end{alertblock}
262+
\end{overprint}
263+
\end{frame}
264+
265+
\begin{frame}[fragile]
266+
\frametitlecpp[11]{Template argument deduction}
267+
\begin{block}{Deduction in partial specializations}
268+
\begin{itemize}
269+
\item Partial specializations also deduce template arguments
270+
\begin{itemize}
271+
\item with similar rules as for function templates
272+
\item but some more restrictions (cf.\ \href{https://en.cppreference.com/w/cpp/language/partial_specialization}{cppreference})
273+
\end{itemize}
274+
\end{itemize}
275+
\end{block}
276+
\small
277+
\begin{cppcode*}{}
278+
template <typename T>
279+
struct S { ... }; // primary template
280+
281+
template <typename T>
282+
struct S<T*> { ... }; // specialization 1
283+
284+
template <typename T, std::size_t N>
285+
struct S<std::array<T*, N>> { ... }; // specialization 2
286+
287+
S<int> s1; // prim. tmpl. (T=int) ok, spec. 1/2 invalid
288+
S<int*> s2; // prim. tmpl. (T=int*) and spec. 1 (T=int) ok
289+
// spec. 1 is more specialized, will be used
290+
\end{cppcode*}
291+
\end{frame}
292+
293+
\begin{frame}[fragile]
294+
\frametitlecpp[98]{Template argument deduction}
295+
\begin{block}{Specialization vs.\ overloading}
296+
\begin{itemize}
297+
\item For function templates we can choose between specialization and overloading
298+
\item Partial specialization of function templates is forbidden
299+
\end{itemize}
300+
\end{block}
301+
\small
302+
\begin{multicols}{2}
303+
\begin{cppcode*}{}
304+
template <typename T>
305+
void f(T t) { ... }
306+
307+
308+
void f(int* t) { ... }
309+
310+
311+
template <typename T>
312+
void f(T* t) { ... }
313+
\end{cppcode*}
314+
\columnbreak
315+
\begin{cppcode*}{}
316+
template <typename T>
317+
void f(T t) { ... }
318+
319+
template <>
320+
void f<int*>(int* t) { ... }
321+
322+
// part. spec. forbidden:
323+
template <typename T>
324+
void f<T*>(T* t) {...}
325+
\end{cppcode*}
326+
\end{multicols}
327+
\end{frame}
328+
329+
\begin{frame}[fragile]
330+
\frametitlecpp[11]{Template argument deduction}
331+
\begin{block}{Disadvantages of specialization vs.\ overloading}
332+
\begin{itemize}
333+
\item Specialization always needs a primary template
334+
\begin{itemize}
335+
\item Sometimes this does not make sense
336+
\end{itemize}
337+
\item Partial specializations of function templates is forbidden
338+
\begin{itemize}
339+
\item So we need SFINAE workarounds or concepts
340+
\end{itemize}
341+
\end{itemize}
342+
\end{block}
343+
\small
344+
\begin{block}{Could you express this with specializations?}
345+
\begin{cppcode}
346+
template <typename T>
347+
void f(T* p) { ... }
348+
349+
template <typename T>
350+
void f(std::unique_ptr<T> p) { ... }
351+
\end{cppcode}
352+
\end{block}
353+
\begin{goodpractice}{Specialization vs.\ overloading}
354+
Prefer overloading function templates over template specialization
355+
\end{goodpractice}
356+
\end{frame}
357+
169358
\begin{frame}[fragile]
170359
\frametitlecpp[17]{Class Template Argument Deduction (CTAD)}
171360
\begin{block}{CTAD}
@@ -238,6 +427,8 @@
238427
\end{block}
239428
\end{frame}
240429

430+
\end{advanced}
431+
241432
\begin{frame}[fragile]
242433
\frametitlecpp[98]{The full power of templates}
243434
\begin{exercise}{Templates}

0 commit comments

Comments
 (0)