# Template metaprogramming 學習筆記
###### tags: `template metaprogramming` `c++11` `template specialization` `partial specialization`
## Introduction
這裡嘗試從 C++11 規格來學習 Template metaprogramming。<sub>(Template metaprogramming 並不是只能在 C\++ 中實現)</sub>
## struct template
[C++11, 21.2 Character traits](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#section.21.2) 提到了一個 `struct template` 和 4 個相關的 `explicit specializations`,`char_traits<char>`、`char_traits<char16_t>`、`char_traits<char32_t>` 和`char_traits<wchar_t>`。先看一段 gcc 的 code 來感受一下 struct template 和 explicit specialization。
[libstdc++\-v3, char_traits.h, line 283](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/char_traits.h#L283)
```cpp
template<class _CharT>
struct char_traits : public __gnu_cxx::char_traits<_CharT>
{ };
```
[libstdc++\-v3, char_traits.h, line 288](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/char_traits.h#L288)
```cpp
/// 21.1.3.1 char_traits specializations
template<>
struct char_traits<char>
{
...
};
```
### 實驗
參考上面 `gcc` 在 `char_traits` 的實作,寫一小段 code 體會一下 `explicit specializations`。
第 8、14 行的` char_traits<char>` 和 `char_traits<wchar_t>` 就是 `char_traits` 的 `explicit specializations`。
```cpp=
#include <iostream>
template<class _CharT>
struct char_traits : public __gnu_cxx::char_traits<_CharT>
{ };
template<>
struct char_traits<char>
{
typedef char char_type;
};
template<>
struct char_traits<wchar_t>
{
typedef wchar_t char_type;
};
int main(){
return 0;
}
```
```
$ gcc template.cpp -lstdc++ -o template
```
## Template function
- Function templates
- Template argument deduction
- Type deduction
- Overload Resolution
從 C++11 <sub>([20.8.11.2 Class template function](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsubsection.20.8.11.2))</sub> 看一下 template function 怎麼寫。
```cpp
template<class> class function; // undefined
template<class R, class... ArgTypes>
class function<R(ArgTypes...)> {
...
};
```
C++11 <sub>([14.5.6 Function templates](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsection.14.5.6))</sub> 對 `function template` 的定義是這樣
> A function template defines an unbounded set of **related** functions.
[C++11 <sub>(14.5.6.2/4 Partial ordering of function templates)</sub>](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsubsection.14.5.6.2) 有一些範例
```cpp
template<class T> void f(T);
template<class T> void f(T*);
template<class T> void f(const T*);
```
### 實驗
參考上述 C++11 規格寫一段 code 來感受一下 function template。
```cpp=
#include <iostream>
using namespace std;
template<class T> void f(T){
std::cout << "f(T)" << std::endl;
};
template<class T> void f(T*){
std::cout << "f(T*)" << std::endl;
};
template<class T> void f(const T*){
std::cout << "f(const T*)" << std::endl;
};
int main(){
const double *p;
f(p);
return 0;
}
```
第 18 行 `f(p);`,如 [C++11 <sub>(14.5.6.2/4 Partial ordering of function templates)</sub>](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsubsection.14.5.6.2) 所說
> f(const T*) is more specialized than f(T) or f(T*)
所以 output 會是 `f(const T*)`
```bash
$ gcc template-func.cpp -lstdc++ -o template-func
$ ./template-func
f(const T*)
```
<!--
### [Template argument deduction](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsection.14.8.2)
- type deduction
[14.8.2 Template argument deduction](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#subsection.14.8.2)
### 實驗
參考 C++11 對 `template argument deduction` 和 `type deduction` 的說明,寫一段 code 實驗一下。
### [Overload Resolution](https://en.cppreference.com/w/cpp/language/overload_resolution)
- decltype
-->
## Template specialization
- C++11 對 Template specialization 的定義
- partial specialization
[`C++11 規格, 14.5.5.3`](http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3376.pdf#subsubsection.14.5.5.3) 對 Template specialization 的定義是這樣
> A class template specialization is a **distinct** template. The members of the class template partial specialization are **unrelated** to the members of the primary template.
舉例說明 template specialization 和 partial specialization
```cpp=
template<class T, int I> struct A {
void f();
};
template<class T, int I> void A<T, I>::f() { };
template<class T> struct A<T, 2> {
void f();
};
int main()
{
A<char, 2> a2;
a2.f(); // 不會呼叫 template<class T, int I> void A<T, I>::f() { };
return 0;
}
```
`A<T, I>::f()` 和 `A<T, 2>::f()` 是 **unrelated**,所以 `A<char, 2>` 是未定義的。因此,link 的時候會出現以下的 error:**(link-time 就可以發現這個 error,不用等到 run-time)**
```shell
$ gcc -std=c++11 test.cpp -o test
/tmp/ccw9gLnA.o: 於函式 main:
test.cpp:(.text+0x1f): 未定義參考到 A<char, 2>::f()
collect2: error: ld returned 1 exit status
```
<!--
## SFINAE
- [Overload Resolution](https://en.cppreference.com/w/cpp/language/overload_resolution)
- [Solving the SFINAE problem for expressions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html)
- [An introduction to C++'s SFINAE concept: compile-time introspection of a class member, Jean Guegant](https://jguegant.github.io/blogs/tech/sfinae-introduction.html)
- [C++ 隨翻: 認識 SFINAE](http://twtedlin31.blogspot.com/2016/03/sfinae.html)
### [Overload Resolution](https://en.cppreference.com/w/cpp/language/overload_resolution)
- [Argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)
- [Template argument deduction](https://en.cppreference.com/w/cpp/language/template_argument_deduction)
這裡再把 Overload Resolution 做一個完整的說明。
### 實驗
## 當 Template 加上繼承
接著看一個例子
[[github, LLVM, atomic, line 1641](https://github.com/llvm-mirror/libcxx/blob/master/include/atomic#L1641)]
```cpp
template <class _Tp>
struct atomic
: public __atomic_base<_Tp>
{
typedef __atomic_base<_Tp> __base;
...
};
```
-->
## Reference
- [ ] [P00557r1, Concepts: The Future of Generic Programmingor How to design good concepts and use them well, Bjarne Stroustrup, 2017-01-31](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0557r0.pdf)
- [ ] [C++ Templates are Turing Complete (2003), Todd L. Veldhuizen](https://pdfs.semanticscholar.org/55a1/417c034899636e736cfb168071555641dece.pdf)