lang:cpp:templatespecialisation
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| lang:cpp:templatespecialisation [2021/04/21 13:00] – Importation des codes de spécialisation des template root | lang:cpp:templatespecialisation [2025/11/14 12:02] (Version actuelle) – Réécriture complète root | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ====Décorateur==== | + | =====Spécialisation complète===== |
| - | [[https:// | + | ====Appeler la méthode généralisée depuis la méthode spécialisée==== |
| + | |||
| + | C'est impossible. La solution est que la méthode de base s' | ||
| - | * implicit return type | ||
| <code cpp> | <code cpp> | ||
| - | # | + | template<typename T> |
| - | #include < | + | void baseF(T t) { ... } |
| - | struct Action1 | + | template< |
| - | struct Action2 { }; | + | void F(T t) { baseF< |
| - | class Classe | + | template<> |
| - | { | + | void F< |
| - | public: | + | </ |
| - | // Default template. | + | |
| - | | + | [[https:// |
| - | auto go(Args ...args) | + | |
| - | | + | ====Empêcher l' |
| - | // | + | |
| - | | + | |
| - | }; | + | |
| - | // Action 1. | + | '' |
| - | template<> | + | |
| - | auto Classe::go<Action1>() | + | <code cpp> |
| - | { | + | #include < |
| - | std::cout << | + | |
| + | template <typename T> | ||
| + | struct foobar | ||
| + | |||
| + | // Template général. | ||
| + | template | ||
| + | T fun(T a) { | ||
| + | // La variable value n'est évaluée que si la méthode est utilisée. | ||
| + | static_assert(foobar< | ||
| + | | ||
| } | } | ||
| - | // Action 2. | + | template <> |
| - | template<> | + | int fun(int a) { |
| - | auto Classe:: | + | return |
| - | { | + | |
| - | | + | |
| - | | + | |
| } | } | ||
| - | template | + | int main() { |
| - | class Decorator | + | // fun<char>(' |
| + | fun< | ||
| + | // fun< | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Autre exemple avec '' | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | |||
| + | struct A | ||
| { | { | ||
| - | public: | + | using Ty = int; |
| - | | + | }; |
| - | template< | + | struct B {}; |
| - | auto go(Args ...args) | + | |
| - | { | + | // KO, should be OK. |
| - | | + | // using Ttrue = std:: |
| - | | + | // KO |
| - | } | + | // using Tfalse = std::conditional_t<false, A::Ty, B::Ty>; |
| - | | + | |
| - | | + | template <typename T> |
| + | struct LazyLoadIdentity | ||
| + | { | ||
| + | using type = T; | ||
| }; | }; | ||
| + | |||
| + | template < | ||
| + | struct LazyLoadTy : LazyLoadIdentity< | ||
| + | |||
| + | // OK | ||
| + | using Ttrue = std:: | ||
| + | // KO | ||
| + | //using Tfalse = std:: | ||
| </ | </ | ||
| - | * explicit return | + | [[https:// |
| + | |||
| + | ====Exemples==== | ||
| + | |||
| + | ===Décorateur (spécialisation sur type)=== | ||
| + | |||
| + | [[https:// | ||
| <code cpp> | <code cpp> | ||
| - | #include < | + | #include < |
| #include < | #include < | ||
| - | struct Action1 { using Type = void; }; | + | struct Action1 { }; |
| - | struct Action2 { using Type = char; }; | + | struct Action2 { }; |
| class Classe | class Classe | ||
| Ligne 67: | Ligne 99: | ||
| public: | public: | ||
| // Default template. | // Default template. | ||
| - | template< | + | template< |
| - | | + | |
| { | { | ||
| // | // | ||
| Ligne 76: | Ligne 108: | ||
| // Action 1. | // Action 1. | ||
| template<> | template<> | ||
| - | Action1:: | + | auto Classe:: |
| { | { | ||
| std::cout << " | std::cout << " | ||
| Ligne 83: | Ligne 115: | ||
| // Action 2. | // Action 2. | ||
| template<> | template<> | ||
| - | Action2:: | + | auto Classe:: |
| { | { | ||
| - | std::cout << " | + | std::cout << " |
| - | return i; | + | return |
| } | } | ||
| Ligne 99: | Ligne 131: | ||
| { | { | ||
| std::cout << " | std::cout << " | ||
| - | return classe-> | + | return classe-> |
| } | } | ||
| private: | private: | ||
| Ligne 106: | Ligne 138: | ||
| </ | </ | ||
| - | * main.cc | + | <file cpp main.cc> |
| - | + | ||
| - | <code cpp> | + | |
| int main() | int main() | ||
| { | { | ||
| Ligne 115: | Ligne 145: | ||
| c.go< | c.go< | ||
| } | } | ||
| - | </code> | + | </file> |
| - | + | ||
| - | ====metaprogrammation vs constexpr==== | + | |
| - | ===Exemple simple=== | + | |
| - | <code cpp> | + | |
| - | #include < | + | |
| - | + | ||
| - | template < | + | |
| - | constexpr T square(T x) { | + | |
| - | return x*x; | + | |
| - | } | + | |
| - | + | ||
| - | int main() { | + | |
| - | printf(" | + | |
| - | // 11.560000 9 | + | |
| - | } | + | |
| - | </code> | + | |
| - | ===Fibonacci=== | + | ===Fibonacci |
| * Template | * Template | ||
| Ligne 183: | Ligne 197: | ||
| <WRAP center round important 60%> | <WRAP center round important 60%> | ||
| - | Le code est beaucoup moins optimisé | + | Le code est beaucoup moins optimisé avec constexpr. Il aurait fallu d' |
| </ | </ | ||
| - | ===Nombres premiers=== | + | ===Nombres premiers |
| * Template | * Template | ||
| Ligne 247: | Ligne 261: | ||
| gcc et clang arrive à calculer à la compilation. | gcc et clang arrive à calculer à la compilation. | ||
| - | ====Appeler la méthode généralisée depuis la méthode spécialisée==== | + | =====Spécialisation partielle===== |
| - | C'est impossible. | + | |
| + | ====Template imbriqué==== | ||
| + | |||
| + | Il faut spécialiser le template parent avant de pouvoir spécialiser le template enfant. | ||
| + | |||
| + | * Classe template | ||
| <code cpp> | <code cpp> | ||
| template< | template< | ||
| - | void baseF(T t) { ... } | + | class A |
| + | { | ||
| + | template< | ||
| + | class B | ||
| + | { | ||
| + | }; | ||
| + | }; | ||
| - | template< | + | // OK |
| - | void F(T t) { baseF<T>(t); } | + | template<> |
| + | template< | ||
| + | class A<int>::B | ||
| + | { | ||
| + | int b; | ||
| + | }; | ||
| + | // KO | ||
| + | template< | ||
| template<> | template<> | ||
| - | void F<int>(int t) { baseF<int>(t); } | + | class A<T>::B<int> |
| + | { | ||
| + | int b; | ||
| + | }; | ||
| </ | </ | ||
| - | [[https:// | + | ====Fonction |
| + | Il n'est pas possible de faire de la spécialisation partielle de template comme pour les classes. | ||
| + | |||
| + | * '' | ||
| + | |||
| + | Il est possible d' | ||
| + | |||
| + | '' | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | |||
| + | struct I { | ||
| + | using R = int; | ||
| + | }; | ||
| + | |||
| + | struct F { | ||
| + | using R = float; | ||
| + | }; | ||
| + | |||
| + | class A { | ||
| + | | ||
| + | template < | ||
| + | static typename std:: | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | template < | ||
| + | static typename std:: | ||
| + | return 27; | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | int main() { return A:: | ||
| + | </ | ||
| + | |||
| + | * Utilisation d'une classe | ||
| + | |||
| + | Si la méthode est static, le plus simple est de passer par des classes qui ne contionnent qu'une seule méthode, celle à spécialiser partiellement. | ||
| + | |||
| + | <code cpp> | ||
| + | template < | ||
| + | struct A { | ||
| + | static int foo(U) { return 1; } | ||
| + | }; | ||
| + | |||
| + | template < | ||
| + | struct A<T, int> { | ||
| + | static int foo(int) { return 2; } | ||
| + | }; | ||
| + | </ | ||
lang/cpp/templatespecialisation.1619002822.txt.gz · Dernière modification : de root
