# 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)