# 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 ![Templates, templates everywhere](https://i.imgflip.com/392pno.jpg) --- ### 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}]"}
    348 views