-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
1a8e85e
commit fe41501
Showing
1 changed file
with
834 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,834 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "35dcd074", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"# Object-oriented scientific programming with C++\n", | ||
"\n", | ||
"Matthias Möller, Jonas Thies, Cálin Georgescu, Jingya Li (Numerical Analysis, DIAM)\n", | ||
"\n", | ||
"Lecture 4" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "3a57f6c5", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Overview</center>\n", | ||
"Last lecture we started with **template meta programming**\n", | ||
"- Implement type-independent functionality\n", | ||
" - Class templates/function templates\n", | ||
" - Generic attributes being able to hold arbitrary data type\n", | ||
" - Generic member function realizing the default behaviour\n", | ||
"- Implement specialized variants of member functions to support special behaviour, e.g., dot product for complex types\n", | ||
"- Instantiate class with concrete types (double, float, etc.)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "8e82d027", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Instantiate class with concrete types (double, float, etc.)</center>\n", | ||
"C++ allows you to **partially specialize** class templates\n", | ||
"```C++\n", | ||
"template<typename S>\n", | ||
"std::complex<S> Vector<std::complex<S> >::\n", | ||
"dot(const Vector<std::complex<S> > other) const { std::complex<S> d=0;\n", | ||
"for (auto i=0; i<n; i++)\n", | ||
" d += data[i]*std::conj(other.data[i]);\n", | ||
" return d;\n", | ||
"}\n", | ||
"```\n", | ||
"Note that this code will not compile. We will see why and learn remedies. Welcome to where template magic begins!" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "9c8204d4", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Overview</center>\n", | ||
"Today, **advanced template meta programming**\n", | ||
"- Full template specialization of complete classes\n", | ||
"- Full template specialization of individual member functions\n", | ||
"- Partial template specialization of class templates\n", | ||
"- Type traits\n", | ||
"- SFINAE paradigm" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "390afba6", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Template specialization</center>\n", | ||
"Type-independent **default implementation**\n", | ||
"```C++\n", | ||
"template<typename T, typename I>\n", | ||
"struct Demo {\n", | ||
" static void info() {\n", | ||
" std::cout << “Generic info“ << std::endl; }\n", | ||
" static void test() {\n", | ||
" std::cout << “Generic test“ << std::endl; }\n", | ||
"};\n", | ||
"```\n", | ||
"This implementation is used whenever there is no (partial) specialization of the `struct Demo` and/oritsfunctions" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c300db4a", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template specialization</center>\n", | ||
"**Task:** implement a template specialization of the entire\n", | ||
"`struct Demo` for `T=float` and `I=long`\n", | ||
"\n", | ||
"Note that template specialization does not imply class inheritance; that is, all attributes/functions that you want to have in a specialized class have to be implemented\n", | ||
"\n", | ||
"Think of class specialization as implementing a new independent `struct Demo<float, long>` thatjusthasthe same name as the generic `struct Demo<T,I>`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ad514241", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template specialization</center>\n", | ||
"**Fully specialized** implementation of the entire **structure**\n", | ||
"```C++\n", | ||
"template<>\n", | ||
"struct Demo<float, long>\n", | ||
"{\n", | ||
" static void info() {\n", | ||
" std::cout << “Fully specialized info“ << std::endl; }\n", | ||
" static void test() {\n", | ||
" std::cout << “Fully specialized test“ << std::endl; }\n", | ||
"};\n", | ||
"```\n", | ||
"\n", | ||
"This implementation is used for the special case\n", | ||
"\n", | ||
"```C++\n", | ||
"Demo<float,long>::info() -> class specialization \n", | ||
"Demo<float,long>::test() -> class specialization\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "aab2b26c", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template specialization</center>\n", | ||
"**Fully specialized** implementation of the entire **structure**\n", | ||
"but without a member function test()\n", | ||
"```C++\n", | ||
"template<>\n", | ||
"struct Demo<float, long>\n", | ||
"{\n", | ||
" static void info() {\n", | ||
" std::cout << “Fully specialized info“ << std::endl; }\n", | ||
"};\n", | ||
"```\n", | ||
"This implementation yields a compiler error\n", | ||
"\n", | ||
"```C++\n", | ||
"Demo<float,long>::info() -> class specialization\n", | ||
"Demo<float,long>::test() // compiler error \n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "6cb3b556", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class-function template specialization</center>\n", | ||
"**Task:** implement a specialization of the member function `info()` for `T=float` and `I=long`\n", | ||
"\n", | ||
"Since we only implement a specialization for the individual function `info()`, the implementation of function `test()` from the non-specialized `struct Demo` remains available\n", | ||
"\n", | ||
"Think of member function specialization as superseding individual member functions by specialized variants" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "40b21ae7", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class-function template specialization</center>\n", | ||
"\n", | ||
"**Fully specialized** implementation of **function** `info()`\n", | ||
"```C++\n", | ||
"template<>\n", | ||
"void Demo<double, long>::info() {\n", | ||
" std::cout << „Fully specialised info“ << std::endl; } \n", | ||
"}\n", | ||
"```\n", | ||
"This implementation provides the specialization of function\n", | ||
"`info()` and the generic implementation of function `test()`\n", | ||
"```C++\n", | ||
"Demo<double,long>::info() -> class-function specialization\n", | ||
"Demo<double,long>::test() -> generic\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "7f320757", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class-function template specialization</center>\n", | ||
"**Fully specialized** implementation of function `info()`\n", | ||
"```C++\n", | ||
"template<>\n", | ||
"void Demo<double, long>::info() {\n", | ||
" std::cout << „Fully specialised info“ << std::endl; } \n", | ||
"}\n", | ||
"```\n", | ||
"This implementation provides the specialization of function\n", | ||
"`info()` andthegeneric implementation of function `test()`\n", | ||
"\n", | ||
"```C++\n", | ||
"Demo<double,long>::info() -> class-function specialization\n", | ||
"Demo<double,long>::test() -> generic\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "6948a035", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template partial specialization</center>\n", | ||
"\n", | ||
"**Task:** implement a specialization of the entire `struct Demo` for `T=float` and arbitrary template parameter value `I`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "b26bf024", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template partial specialization</center>\n", | ||
"**Partially specialized** implementation of the **structure**\n", | ||
"```C++\n", | ||
"template<typename I>\n", | ||
" struct Demo<double, I>\n", | ||
" {\n", | ||
" static void info() {\n", | ||
" std::cout << „Partially specialized info“ << std::endl; }\n", | ||
" static void test() {\n", | ||
" std::cout << „Partially specialized test“ << std::endl; }\n", | ||
"};\n", | ||
"```\n", | ||
"This implementation is used for the special case\n", | ||
"\n", | ||
"```C++\n", | ||
"Demo<double,int>::info() -> partial class specialization\n", | ||
"Demo<double,int>::test() -> partial class specialization\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "be640e26", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Class template partial specialization</center>\n", | ||
"**Task:** implement a specialization of member function `info()` for `T=float` and arbitrary template parameter value `I`\n", | ||
"\n", | ||
"Partial function template specialization is not **possible in C++**\n", | ||
"```C++\n", | ||
"template<typename I>\n", | ||
"void Demo<float, I>::info() {...}\n", | ||
"```\n", | ||
"\n", | ||
"Stay tuned, there are tricks to solve this problem" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "0d8f79de", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Summary template specialization</center>\n", | ||
"Given a templated class with member functions\n", | ||
"- Entire class can be fully or partially specialized\n", | ||
"- Individual member functions can fully specialized\n", | ||
"- Individual member functions **cannot** be partially specialized\n", | ||
"\n", | ||
"Full/partial class specialization is like implementing a new individual class that can be accessed by the same name\n", | ||
"\n", | ||
"Full function specialization is like superseding individual member functions by specialized variants" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "3daf7ddd", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Quiz</center>\n", | ||
"Remember the specialized dot product for complex-valued\n", | ||
"vectors from the previous session, will this work?\n", | ||
"\n", | ||
"```C++\n", | ||
"template<typename T> class Vector {\n", | ||
" T dot(const Vector<T>& other) const {...}\n", | ||
"};\n", | ||
"template<typename S> std::complex<S> \n", | ||
" Vector<std::complex<S> >::\n", | ||
" dot(const Vector<std::complex<S> > other) const {\n", | ||
" std::complex<S> d=0;\n", | ||
" for (auto i=0; i<n; i++)\n", | ||
" d += data[i]*std::conj(other.data[i]);\n", | ||
" return d;\n", | ||
"} \n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "1e5b1bf8", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>SFINAE paradigm</center>\n", | ||
"C++ allows us to write **overloaded functions with different**\n", | ||
"input parameter lists, e.g.,\n", | ||
"```C++\n", | ||
"static void info() {...}\n", | ||
"static void info(int i) {...}\n", | ||
"```\n", | ||
"It is, however, **not** allowed to overload functions that only differ in the type of their return parameter, e.g.,\n", | ||
"```C++\n", | ||
"static void info() {...}\n", | ||
"static int info() {...}\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "f22ba5b8", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>SFINAE paradigm</center>\n", | ||
"C++11 standard states:\n", | ||
"\n", | ||
"<i>If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.</i>\n", | ||
"\n", | ||
"**SFINAE:** <span style=color:red;>S</span>ubstitution <span style=color:red;>F</span>ailure <span style=color:red;>I</span>s <span style=color:red;>N</span>ot <span style=color:red;>A</span>n <span style=color:red;>E</span>rror" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "e3dee20b", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>SFINAE paradigm</center>\n", | ||
"C++11 standard rephrased for our purpose:\n", | ||
"\n", | ||
"<i>If a template substitution leads to invalid code then the compiler must not throw an error but look for another candidate (i.e. the second templated implementation of our function); <b>an error is just thrown if no other candidate can be found</b> so that the function call remains unresolved</i>" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "be2aa4cf", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>SFINAE paradigm</center>\n", | ||
"**SFINAE:** <span style=color:red;>S</span>ubstitution <span style=color:red;>F</span>ailure <span style=color:red;>I</span>s <span style=color:red;>N</span>ot <span style=color:red;>A</span>n <span style=color:red;>E</span>rror\n", | ||
"\n", | ||
"- Write multiple implementations of the same function with\n", | ||
" - the **same name** and\n", | ||
" - the **same input parameters**\n", | ||
"- Ensure – via template meta programming – that **exactly one** at a time results in **valid code** upon substitution of the template parameters and **all other** candidates yield **invalid expressions**" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "d7007a07", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Traits</center>\n", | ||
"Consider the `is_int` **function** from the previous assignment\n", | ||
"```C++\n", | ||
"template<typename T>\n", | ||
"bool is_int(T a) { return false; }\n", | ||
"template<>\n", | ||
"bool is_int<int>(int a) { return true; }\n", | ||
"```\n", | ||
"\n", | ||
"This function returns true/false depending on the type of the parameter passed via explicit template specialisation\n", | ||
"\n", | ||
"We look for an even more elegant solution without the need to call a function and pass a parameter at all" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "709a9bef", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Traits</center>\n", | ||
"Consider the templated `is_int` **structure** with specialization\n", | ||
"```C++\n", | ||
"template<typename T>\n", | ||
"struct is_int\n", | ||
"{\n", | ||
" const static bool value = false;\n", | ||
"};\n", | ||
"template<>\n", | ||
"struct is_int<int>\n", | ||
"{\n", | ||
" const static bool value = true;\n", | ||
"};\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "3577d66d", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Traits</center>\n", | ||
"Detect if a given type is `int` without passing a parameter\n", | ||
"```C++\n", | ||
"std::cout << is_int<int>::value << std::endl;\n", | ||
"std::cout << is_int<double>::value << std::endl;\n", | ||
"```\n", | ||
"The `is_int` **type trait** can be used in templated functions\n", | ||
"```C++\n", | ||
"template<typename T>\n", | ||
"void test(T a)\n", | ||
"{\n", | ||
" if (is_int<T>::value)\n", | ||
" std::cout << „Integer :“ << a << std::endl;\n", | ||
" else\n", | ||
" std::cout << „Non-Int :“ << a << std::endl;\n", | ||
"}\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "5ab6d885", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Traits</center>\n", | ||
"The `is_int` **type trait** is evaluated at compile time in contrast to the `is_int()` **function** which (theoretically) might trigger an extra function call at run time (slow!)\n", | ||
"\n", | ||
"A smart compiler will eliminate the if-else clause\n", | ||
"\n", | ||
"```C++\n", | ||
"void test(int a)\n", | ||
" {\n", | ||
" if (is_int<T>::value)\n", | ||
" std::cout << \"Integer :\" << a << std::endl;\n", | ||
" else\n", | ||
" std::cout << \"Non-Int :\" << a << std::endl;\n", | ||
"}\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "7e5e9d04", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Traits</center>\n", | ||
"C++ brings many **type traits** via `#include <type_traits>`\n", | ||
"<table border=\"1\">\n", | ||
" <tr>\n", | ||
" <th>Function</th>\n", | ||
" <th>Description</th>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_class<T></td>\n", | ||
" <td>Type T is of class type</td>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_const<T></td>\n", | ||
" <td>Type T has const qualifier</td>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_floating_point<T></td>\n", | ||
" <td>Type T is floating point (float, double, long)</td>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_fundamental<T></td>\n", | ||
" <td>Type T is of fundamental type (int, double, ...)</td>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_integral<T></td>\n", | ||
" <td>Type T is of integral type (int, long int, ...)</td>\n", | ||
" </tr>\n", | ||
" <tr>\n", | ||
" <td>is_pointer<T></td>\n", | ||
" <td>Type T is of pointer type</td>\n", | ||
" </tr>\n", | ||
"</table>\n", | ||
"\n", | ||
"For a complete list of standard type traits look at:http://www.cplusplus.com/reference/type_traits/" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "9c0b9ee8", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Type traits</center>\n", | ||
"The aforementioned C++ **standard type traits** provide\n", | ||
"- Member constants:\n", | ||
" `value (=true/false)`\n", | ||
"- Member types:\n", | ||
" `value_type (=bool)`\n", | ||
" \n", | ||
" `type (=true_type/false_type)`\n", | ||
"Member constants/types can be directly accessed\n", | ||
"```C++\n", | ||
"is_fundamental<int>::value // true\n", | ||
"is_fundamental<int>::value_type // bool \n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "4fccc3ef", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Types Traits</center>\n", | ||
"C++ provides type traits that **operate on the type**\n", | ||
"```C++\n", | ||
"typedef add_const<int> A // const int\n", | ||
"typedef add_const<const int> B // const int (unchanged)\n", | ||
" \n", | ||
"typedef add_pointer<int> C // int*\n", | ||
"typedef add_pointer<const int> D // const int*\n", | ||
"typedef add_pointer<int&> E // int*\n", | ||
"typedef add_pointer<int*> F // int**\n", | ||
"typedef add_pointer<int(int)> G // int(*)int\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "30ccb64c", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Types Traits</center>\n", | ||
"C++ provides type traits that **operate on the type**\n", | ||
"\n", | ||
"```C++\n", | ||
"typedef remove_const<int> A // int (unchanged)\n", | ||
"typedef remove_const<const int> B // int\n", | ||
"\n", | ||
"typedef remove_pointer<int> C //int\n", | ||
"typedef remove_pointer<int*> D //int\n", | ||
"typedef remove_pointer<int**> E //int*\n", | ||
"typedef remove_pointer<const int> F //const int\n", | ||
"typedef remove_pointer<const int*> G //const int\n", | ||
"typedef remove_pointer<int* const> H //int\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "1855cf1b", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Types Traits</center>\n", | ||
"C++ provides type traits that **operate on two types:**\n", | ||
"Check if two types are **exactly** the same (including qualifiers)\n", | ||
"\n", | ||
"```C++\n", | ||
"bool is_same<A, B>::value\n", | ||
"\n", | ||
"bool is_same<int, int>::value // true\n", | ||
"bool is_same<int, const int>::value // false\n", | ||
"bool is_same<remove_const<int>,\n", | ||
" remove_const<const int> >::value // true\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "15351b18", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Type Traits</center>\n", | ||
"C++ provides type traits that **operate on two types:**\n", | ||
"\n", | ||
"Check if type B is derived from type A\n", | ||
"\n", | ||
"```C++\n", | ||
"struct A {};\n", | ||
"struct B : A {};\n", | ||
"bool is_base_of<A, B>::value\n", | ||
" \n", | ||
"bool is_base_of<A, A>::value // true\n", | ||
"bool is_base_of<A, B>::value // true\n", | ||
"bool is_base_of<B, A>::value // false\n", | ||
"bool is_base_of<B, B>::value // true\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "b821d37a", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Type Traits</center>\n", | ||
"C++ provides type trait to **enable types conditionally**\n", | ||
"```C++\n", | ||
"template<typename T>\n", | ||
"typename std::enable_if<std::is_integral<T>::value,\n", | ||
" bool>::type\n", | ||
"is_odd(T i) { return bool(i%2); }\n", | ||
"int i=2;\n", | ||
"cout << „i is odd :“ << is_odd(i) << endl;\n", | ||
"```\n", | ||
"If `is_odd` is called with an **integral type** (e.g., `int`) the compiler\n", | ||
"expands the above templated function as follows\n", | ||
"\n", | ||
"```C++\n", | ||
"bool is_odd(int i) { return bool(i%2); }\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "211c8f0f", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "subslide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>Intermezzo: Type Traits</center>\n", | ||
"C++ provides type trait to **enable types conditionally**\n", | ||
"```C++\n", | ||
"template<typename T>\n", | ||
"typename std::enable_if<std::is_integral<T>::value,\n", | ||
" bool>::type\n", | ||
"is_odd(T i) { return bool(i%2); }\n", | ||
"float i=2;\n", | ||
"cout << „i is odd :“ << is_odd(i) << endl;\n", | ||
"```\n", | ||
"\n", | ||
"If `is_odd` is called with a **non-integral type** (e.g., `float`) the compiler expands the above templated function as follows\n", | ||
"\n", | ||
"```C++\n", | ||
"is_odd(float i) { return bool(i%2); } // compiler error\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "f8522388", | ||
"metadata": { | ||
"slideshow": { | ||
"slide_type": "slide" | ||
} | ||
}, | ||
"source": [ | ||
"## <center>SFINAE paradigm</center>\n", | ||
"**SFINAE:** <span style=color:red;>S</span>ubstitution <span style=color:red;>F</span>ailure <span style=color:red;>I</span>s <span style=color:red;>N</span>ot <span style=color:red;>A</span>n <span style=color:red;>E</span>rror\n", | ||
"\n", | ||
"- Write multiple implementations of the same function with\n", | ||
" - the **same name** and\n", | ||
" - the **same input parameters**\n", | ||
"- Ensure using the `enable_if` **type trait** that exactly one at a time results in **valid code** upon substitution of template parameters and **all other** candidates yield **invalid expressions**" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "18b86abf", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "6d59f4ce", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "3647a872", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "89021cec", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "0642d6a0", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"celltoolbar": "Slideshow", | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.11.5" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |