|
25 | 25 | \begin{cppcode*}{}
|
26 | 26 | template
|
27 | 27 | <typename T,
|
28 |
| - typename = typename std::enable_if_t<std::is_floating_point_v<T>> |
| 28 | + typename = std::enable_if_t<std::is_floating_point_v<T>> |
29 | 29 | bool equal( T e1, T e2 ) {
|
30 |
| - return abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
| 30 | + return std::abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
31 | 31 | }
|
32 | 32 | ... equal(10,5+5) ...
|
33 | 33 | \end{cppcode*}
|
|
53 | 53 | \frametitlecpp[20]{Basic requirements}
|
54 | 54 | \begin{block}{A new keyword}
|
55 | 55 | \begin{itemize}
|
56 |
| - \item The keyword \mintinline{cpp}{requires} let us define various constraints. |
| 56 | + \item The keyword \mintinline{cpp}{requires} lets us define various constraints. |
57 | 57 | \end{itemize}
|
58 | 58 | \end{block}
|
59 | 59 | \begin{exampleblock}{With concepts}
|
|
62 | 62 | template<typename T>
|
63 | 63 | requires std::is_floating_point_v<T>
|
64 | 64 | bool equal( T e1, T e2 ) {
|
65 |
| - return abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
| 65 | + return std::abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
66 | 66 | }
|
67 | 67 | ... equal(10,5+5) ...
|
68 | 68 | \end{cppcode*}
|
|
95 | 95 | template< typename T>
|
96 | 96 | requires std::is_floating_point_v<T>
|
97 | 97 | bool equal( T e1, T e2 )
|
98 |
| - { return abs(e1-e2)<std::numeric_limits<T>::epsilon(); } |
| 98 | + {return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();} |
99 | 99 | \end{cppcode*}
|
100 | 100 | \end{exampleblock}
|
101 | 101 | \begin{block}{Requirements affect overload resolution}
|
|
110 | 110 | \begin{block}{Definition}
|
111 | 111 | \begin{itemize}
|
112 | 112 | \item a \textbf{concept} gives a name to a given set of requirements
|
113 |
| - \item useful when requirements are reused often |
| 113 | + \item useful when the same requirements are reused frequently |
114 | 114 | \end{itemize}
|
115 | 115 | \end{block}
|
116 |
| - \begin{exampleblock}{A new keyword : {\it concept}} |
| 116 | + \begin{exampleblock}{A new keyword: \texttt{concept}} |
117 | 117 | \small
|
118 | 118 | \begin{cppcode*}{gobble=2}
|
119 | 119 | template< typename T>
|
120 | 120 | concept MyFloatingPoint =
|
121 |
| - (std::is_floating_point_v<T>) && |
122 |
| - (std::numeric_limits<T>::epsilon()>0); |
| 121 | + std::is_floating_point_v<T> && |
| 122 | + std::numeric_limits<T>::epsilon()>0; |
123 | 123 |
|
124 | 124 | template<typename T>
|
125 | 125 | requires MyFloatingPoint<T>
|
126 | 126 | bool equal( T e1, T e2 )
|
127 |
| - { return abs(e1-e2)<std::numeric_limits<T>::epsilon(); } |
| 127 | + {return std::abs(e1-e2)<std::numeric_limits<T>::epsilon();} |
128 | 128 | \end{cppcode*}
|
129 | 129 | \end{exampleblock}
|
130 | 130 | \end{frame}
|
131 | 131 |
|
132 | 132 | \begin{frame}[fragile]
|
133 | 133 | \frametitlecpp[20]{Some usages of concepts}
|
134 |
| - \begin{block}{Concepts as template parameters} |
| 134 | + \begin{block}{Constrained template parameters} |
135 | 135 | \begin{itemize}
|
136 |
| - \item concepts can be used in template parameter lists |
137 |
| - \item replacing \mintinline{cpp}{typename} |
| 136 | + \item a concept can replace \mintinline{cpp}{typename} in a template parameter lists |
138 | 137 | \end{itemize}
|
139 | 138 | \end{block}
|
140 | 139 | \begin{exampleblock}{}
|
141 | 140 | \small
|
142 | 141 | \begin{cppcode*}{gobble=2}
|
143 | 142 | template<MyFloatingPoint T>
|
144 | 143 | bool equal( T e1, T e2 ) {
|
145 |
| - return abs(e1-e2) < std::numeric_limits<T>::epsilon(); |
| 144 | + return std::abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
146 | 145 | }
|
147 | 146 | \end{cppcode*}
|
148 | 147 | \end{exampleblock}
|
149 |
| - \begin{block}{Concepts in abbreviated function arguments} |
| 148 | + \begin{block}{Constrained variables} |
150 | 149 | \begin{itemize}
|
151 |
| - \item concepts can be used together with \mintinline{cpp}{auto} in abbreviated function templates |
| 150 | + \item a concept can be used together with \mintinline{cpp}{auto} to impose requirements on the type of a variable |
| 151 | + \end{itemize} |
| 152 | + \end{block} |
| 153 | + \begin{exampleblock}{firstnumber=4,gobble=2} |
| 154 | + \begin{cppcode*}{firstnumber=4,gobble=2} |
| 155 | + MyFloatingPoint auto f = 3.14f; |
| 156 | + MyFloatingPoint auto d = 3.14; |
| 157 | + MyFloatingPoint auto i = 3; // compile error |
| 158 | + \end{cppcode*} |
| 159 | + \end{exampleblock} |
| 160 | +\end{frame} |
| 161 | + |
| 162 | + |
| 163 | +\begin{frame}[fragile] |
| 164 | + \frametitlecpp[20]{Some usages of concepts} |
| 165 | + \begin{block}{Abbreviated function templates} |
| 166 | + \begin{itemize} |
| 167 | + \item function parameters, similar to variables, can be constrained as well |
| 168 | + \item the template head becomes obsolete |
| 169 | + \item the function is still a template though! |
| 170 | + \item unconstrained \mintinline{cpp}{auto} parameters are allowed as well |
152 | 171 | \end{itemize}
|
153 | 172 | \end{block}
|
154 | 173 | \begin{exampleblock}{}
|
155 | 174 | \small
|
156 |
| - \begin{cppcode*}{firstnumber=4,gobble=2} |
| 175 | + \begin{cppcode*}{gobble=2} |
| 176 | + // no template <...> here! |
157 | 177 | bool equal( MyFloatingPoint auto e1,
|
158 | 178 | MyFloatingPoint auto e2 ) {
|
159 |
| - return abs(e1-e2) < |
160 |
| - std::numeric_limits<decltype(e1)>::epsilon(); } |
| 179 | + return std::abs(e1-e2) < |
| 180 | + std::numeric_limits<decltype(e1)>::epsilon(); |
| 181 | + } |
| 182 | + |
| 183 | + // unconstrained abbreviated function template: |
| 184 | + void equal(auto e1, auto e2) { ... } |
161 | 185 | \end{cppcode*}
|
162 | 186 | \end{exampleblock}
|
163 | 187 | \end{frame}
|
|
170 | 194 | \item Prefer the ones provided by the standard library
|
171 | 195 | \end{itemize}
|
172 | 196 | \end{block}
|
173 |
| - \begin{exampleblock}{E.g. : the floating point concept} |
| 197 | + \begin{exampleblock}{E.g.: the floating point concept} |
174 | 198 | \small
|
175 | 199 | \begin{cppcode*}{gobble=2}
|
176 | 200 | #include <concepts>
|
177 | 201 | bool equal( std::floating_point auto e1,
|
178 | 202 | std::floating_point auto e2 ) {
|
179 |
| - return abs(e1-e2) < |
| 203 | + return std::abs(e1-e2) < |
180 | 204 | std::numeric_limits<decltype(e1)>::epsilon();
|
181 | 205 | }
|
182 | 206 | \end{cppcode*}
|
183 | 207 | \end{exampleblock}
|
184 | 208 | \end{frame}
|
185 | 209 |
|
186 | 210 | \begin{frame}[fragile]
|
187 |
| - \frametitlecpp[20]{Concepts checking} |
188 |
| - \begin{block}{Concepts as boolean operators} |
| 211 | + \frametitlecpp[20]{Checking concepts} |
| 212 | + \begin{block}{Concepts as Boolean operators} |
189 | 213 | \begin{itemize}
|
190 |
| - \item Concepts can be used wherever a boolean is expected |
| 214 | + \item Concepts can be used wherever a \mintinline{c}{bool} is expected |
191 | 215 | \item they can appear in \mintinline{cpp}{if constexpr} conditions
|
192 | 216 | \begin{itemize}
|
193 | 217 | \item since they are evaluated at compile-time
|
194 | 218 | \end{itemize}
|
195 | 219 | \end{itemize}
|
196 | 220 | \end{block}
|
197 |
| - \begin{exampleblock}{Using concepts with {\it if constexpr}} |
| 221 | + \begin{exampleblock}{Using concepts with \texttt{if constexpr}} |
198 | 222 | \small
|
199 | 223 | \begin{cppcode*}{gobble=2}
|
200 | 224 | template<typename T>
|
201 | 225 | bool equal( T e1, T e2 )
|
202 | 226 | {
|
203 | 227 | if constexpr (std::floating_point<T>) {
|
204 |
| - return abs(e1-e2)<std::numeric_limits<T>::epsilon(); |
| 228 | + return std::abs(e1-e2) |
| 229 | + < std::numeric_limits<T>::epsilon(); |
205 | 230 | } else {
|
206 | 231 | return (e1==e2);
|
207 | 232 | }
|
|
225 | 250 | \begin{cppcode*}{gobble=2}
|
226 | 251 | template<typename T>
|
227 | 252 | concept StreamableAndComparableNumber =
|
228 |
| - requires( T v1, T v2 ) { |
| 253 | + requires( T v1, T v2, std::ostream os ) { |
229 | 254 | requires std::integral<T> || std::floating_point<T>;
|
230 |
| - std::cout<<v1<<v2; |
| 255 | + os<<v1<<v2; |
231 | 256 | { equal(v1,v2) } -> std::convertible_to<bool>;
|
232 | 257 | };
|
233 | 258 | \end{cppcode*}
|
234 | 259 | \end{exampleblock}
|
235 |
| - Remember : use standard concepts first |
| 260 | + \begin{block}{} |
| 261 | + Remember : use standard concepts first |
| 262 | + \end{block} |
236 | 263 | \end{frame}
|
237 | 264 |
|
238 | 265 | \begin{frame}
|
239 | 266 | \frametitlecpp[20]{Requirements and concepts}
|
240 |
| - \begin{block}{To be remembered} |
| 267 | + \begin{block}{Summary} |
241 | 268 | \begin{itemize}
|
242 | 269 | \item A template can now \emph{require} properties of its parameters
|
243 | 270 | \item Compiler error messages clearly state which argument does not fulfill which requirement
|
244 | 271 | \item A set of requirements can be gathered in a \emph{concept}
|
245 | 272 | \item Overload resolution takes requirements into account
|
246 | 273 | \item The standard library provides many ready-to-use concepts
|
247 |
| - \item Writing a new good concept is an expert topic |
| 274 | + \item Writing a new good concept is an expert task |
248 | 275 | \end{itemize}
|
249 | 276 | \end{block}
|
250 | 277 | \end{frame}
|
251 | 278 |
|
252 | 279 | \begin{frame}
|
253 |
| - \frametitlecpp[11]{Exercise time} |
| 280 | + \frametitlecpp[20]{Exercise time} |
254 | 281 | \begin{exercise}{Concepts}
|
255 | 282 | \begin{itemize}
|
256 | 283 | \item go to code/concepts
|
|
0 commit comments