lang:cpp:templatespecialisation
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| lang:cpp:templatespecialisation [2021/04/21 13:19] – Ajout de "Empêcher l'utilisation du template non spécialisé" root | lang:cpp:templatespecialisation [2025/11/14 12:02] (Version actuelle) – Réécriture complète root | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ====Divers==== | + | =====Spécialisation complète===== |
| - | ===Empêcher l' | + | ====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' | ||
| + | |||
| + | <code cpp> | ||
| + | template< | ||
| + | void baseF(T t) { ... } | ||
| + | |||
| + | template< | ||
| + | void F(T t) { baseF< | ||
| + | |||
| + | template<> | ||
| + | void F< | ||
| + | </ | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | ====Empêcher l' | ||
| - | '' | + | '' |
| <code cpp> | <code cpp> | ||
| Ligne 14: | Ligne 31: | ||
| template <class T> | template <class T> | ||
| T fun(T a) { | T fun(T a) { | ||
| + | // La variable value n'est évaluée que si la méthode est utilisée. | ||
| static_assert(foobar< | static_assert(foobar< | ||
| "this function has to be implemented for desired type" | "this function has to be implemented for desired type" | ||
| Ligne 30: | Ligne 48: | ||
| </ | </ | ||
| + | Autre exemple avec '' | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | |||
| + | struct A | ||
| + | { | ||
| + | using Ty = int; | ||
| + | }; | ||
| + | |||
| + | struct B {}; | ||
| + | |||
| + | // KO, should be OK. | ||
| + | // using Ttrue = std:: | ||
| + | // KO | ||
| + | // using Tfalse = std:: | ||
| + | |||
| + | template < | ||
| + | struct LazyLoadIdentity | ||
| + | { | ||
| + | using type = T; | ||
| + | }; | ||
| + | |||
| + | template < | ||
| + | struct LazyLoadTy : LazyLoadIdentity< | ||
| + | |||
| + | // OK | ||
| + | using Ttrue = std:: | ||
| + | // KO | ||
| + | //using Tfalse = std:: | ||
| + | </ | ||
| + | |||
| + | [[https:// | ||
| + | ====Exemples==== | ||
| - | ====Décorateur==== | + | ===Décorateur |
| [[https:// | [[https:// | ||
| - | * implicit return type | ||
| <code cpp> | <code cpp> | ||
| #include < | #include < | ||
| Ligne 87: | Ligne 138: | ||
| </ | </ | ||
| - | * explicit return type | + | <file cpp main.cc> |
| - | + | ||
| - | <code cpp> | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | + | ||
| - | struct Action1 { using Type = void; }; | + | |
| - | struct Action2 { using Type = char; }; | + | |
| - | + | ||
| - | class Classe | + | |
| - | { | + | |
| - | public: | + | |
| - | // Default template. | + | |
| - | template< | + | |
| - | T go(Args ...args) | + | |
| - | { | + | |
| - | // | + | |
| - | } | + | |
| - | }; | + | |
| - | + | ||
| - | // Action 1. | + | |
| - | template<> | + | |
| - | Action1:: | + | |
| - | { | + | |
| - | std::cout << " | + | |
| - | } | + | |
| - | + | ||
| - | // Action 2. | + | |
| - | template<> | + | |
| - | Action2:: | + | |
| - | { | + | |
| - | std::cout << " | + | |
| - | return i; | + | |
| - | } | + | |
| - | + | ||
| - | template <class T> | + | |
| - | class Decorator | + | |
| - | { | + | |
| - | public: | + | |
| - | Decorator(std:: | + | |
| - | + | ||
| - | template< | + | |
| - | auto go(Args ...args) | + | |
| - | { | + | |
| - | std::cout << " | + | |
| - | return classe-> | + | |
| - | } | + | |
| - | private: | + | |
| - | std:: | + | |
| - | }; | + | |
| - | </ | + | |
| - | + | ||
| - | * main.cc | + | |
| - | + | ||
| - | <code cpp> | + | |
| int main() | int main() | ||
| { | { | ||
| Ligne 148: | Ligne 145: | ||
| c.go< | c.go< | ||
| } | } | ||
| - | </code> | + | </file> |
| - | ====metaprogrammation vs constexpr==== | + | ===Fibonacci |
| - | ===Exemple simple=== | + | |
| - | <code cpp> | + | |
| - | #include < | + | |
| - | + | ||
| - | template < | + | |
| - | constexpr T square(T x) { | + | |
| - | return x*x; | + | |
| - | } | + | |
| - | + | ||
| - | int main() { | + | |
| - | printf(" | + | |
| - | // 11.560000 9 | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | ===Fibonacci=== | + | |
| * Template | * Template | ||
| Ligne 216: | 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 280: | 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.1619003975.txt.gz · Dernière modification : de root
