# Template metaprogramming
何震邦 (jdh8)
---
## Metaprogramming
Meta?
---
### Programming
Writing code
### Metaprogramming
Writing code that writes code
---
### Why `template`
---
## Static polymorphism
Same code for different types
Compile-time resolution
---
### STL

---
### STL
- Containers
- Algorithms
- Stream
- `std::ostream = std::basic_ostream<char>`
---
## Function template
```cpp
template<typename T>
T square(T x)
{
return x * x;
}
```
---
### ODR
One Definition Rule
a.cpp: foo(double)
b.cpp: foo(double)
---
## Class template
```cpp
template<typename T, int M, int N>
class Matrix
{
T _data[M * N];
};
Matrix<double, 3, 3> A;
```
---
### Partial specialization
```cpp
template<typename T, int M>
class Matrix<T, M, 1>
{
// Vector-specific stuff
// Warning: this is a brand new type
// and 'inherits' nothing from base template
};
```
---
### Total specialization
```cpp
template<> // 'Concrete' type
class Matrix<void*, 2, 3>
{
/* ... */
};
```
---
## SFINAE
Substitution failure is not an error
```cpp
#include <type_traits>
```
---
### SFINAE example
```cpp
struct Test { typedef int foo; };
template <typename T>
void f(typename T::foo) {}
template <typename T>
void f(T) {}
f<Test>(10);
f<int>(10);
f(10);
```
---
```cpp
template<typename T>
std::false_type has_scope_impl(...);
template<typename T>
std::true_type has_scope_impl(int T::*);
template<typename T>
struct has_scope : decltype(has_scope_impl<T>(0)) {};
```
---
### std::void_t
```cpp
template<typename...>
using void_t = void;
```
---
```cpp
template<typename T, typename = void>
struct has_scope : std::false_type {};
template<typename T>
struct has_scope<T, std::void_t<int T::*>>
: std::true_type
{};
```
---
## Dependent names
---
### ???
```cpp
template<typename To, typename From>
To cast(const From& from)
{
return from.cast<To>(); // compilation error
}
```
---
### `template` disambiguator
C++ is context-sensitive
```cpp
template<typename To, typename From>
To cast(const From& from)
{
return from.template cast<To>();
}
```
---
### ???
```cpp
template<typename T>
void traverse(const std::vector<T>& v)
{
// compilation error
for (std::vector<T>::size_type i = 0; i < v.size(); ++i)
/* ... */;
}
```
---
### `typename` disambiguator
```cpp
template<typename T>
void traverse(const std::vector<T>& v)
{
typedef typename std::vector<T>::size_type Index;
for (Index i = 0; i < v.size(); ++i)
/* ... */;
}
```
---
## Curiously Recurring Template Pattern (CRTP)
Early binding
```cpp
template<typename Derived>
struct Animal
{
void speak() { static_cast<Derived*>(this)->speak(); }
};
struct Dog : Animal<Dog>
{
void speak() { std::cout << "Woof!"; }
};
```
---
### Dynamic polymorphism
Late binding
```cpp
struct Animal
{
virtual void speak() = 0;
};
struct Dog : Animal
{
void speak() override { std::cout << "Woof!"; }
};
```
---
### OOF
```cpp
template<typename Derived>
struct Animal
{
void speak() { static_cast<Derived*>(this)->speak(); }
};
struct Fake : Animal<Fake> {};
Fake().speak(); // XXX
```
---
### Solution (C++14)
```cpp
template<typename Derived>
struct Animal
{
auto speak() { return static_cast<Derived*>(this)->speak(); }
};
struct Dog : Animal<Dog>
{
void speak() { std::cout << "Woof!"; }
};
```
---
## Thanks
You can find me on
[GitHub](https://github.com/jdh8)
{"metaMigratedAt":"2023-06-14T23:30:49.293Z","metaMigratedFrom":"YAML","title":"Template metaprogramming","breaks":true,"description":"View the slide with \"Slide Mode\".","contributors":"[{\"id\":\"24afb771-a37f-4061-99c6-a401980a9d39\",\"add\":6522,\"del\":2892}]"}