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/07/05 09:51] – Déplacement de Divers en bas root | lang:cpp:templatespecialisation [2025/11/14 12:02] (Version actuelle) – Réécriture complète root | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ====Spécialisation | + | =====Spécialisation |
| - | ===Il faut commencer par spécialiser le premier template=== | + | ====Appeler la méthode généralisée depuis la méthode spécialisée==== |
| - | * Classe template | + | C'est impossible. La solution est que la méthode de base s' |
| <code cpp> | <code cpp> | ||
| template< | template< | ||
| - | class A | + | void baseF(T t) { ... } |
| - | { | + | |
| - | template< | + | |
| - | class B | + | |
| - | { | + | |
| - | }; | + | |
| - | }; | + | |
| - | // OK | ||
| - | template<> | ||
| - | template< | ||
| - | class A< | ||
| - | { | ||
| - | int b; | ||
| - | }; | ||
| - | |||
| - | // KO | ||
| template< | template< | ||
| - | template<> | + | void F(T t) { baseF<T>(t); } |
| - | class A<T>:: | + | |
| - | { | + | |
| - | int b; | + | |
| - | }; | + | |
| + | template<> | ||
| + | void F< | ||
| </ | </ | ||
| - | * Fonction | + | [[https:// |
| - | Il n'est pas possible de faire de la spécialisation partielle de template | + | ====Empêcher l'utilisation du template |
| - | Mais il est possible | + | '' |
| - | '' | + | <code cpp> |
| + | #include < | ||
| + | |||
| + | template < | ||
| + | struct foobar : std::false_type {}; | ||
| + | |||
| + | // Template général. | ||
| + | template <class T> | ||
| + | T fun(T a) { | ||
| + | // La variable value n'est évaluée que si la méthode | ||
| + | static_assert(foobar< | ||
| + | "this function has to be implemented for desired | ||
| + | } | ||
| + | |||
| + | template <> | ||
| + | int fun(int a) { | ||
| + | return a; | ||
| + | } | ||
| + | |||
| + | int main() { | ||
| + | // fun< | ||
| + | fun< | ||
| + | // fun< | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Autre exemple avec '' | ||
| <code cpp> | <code cpp> | ||
| #include < | #include < | ||
| - | struct | + | struct |
| - | using R = int; | + | { |
| + | using Ty = int; | ||
| }; | }; | ||
| - | struct | + | struct |
| - | using R = float; | + | |
| - | }; | + | |
| - | class A { | + | // KO, should be OK. |
| - | public: | + | // using Ttrue = std:: |
| - | template | + | // KO |
| - | | + | // using Tfalse = std::conditional_t<false, A::Ty, B::Ty>; |
| - | return 1; | + | |
| - | } | + | |
| - | | + | template < |
| - | | + | struct LazyLoadIdentity |
| - | return 27; | + | { |
| - | } | + | |
| }; | }; | ||
| - | int main() | + | template < |
| + | struct LazyLoadTy : LazyLoadIdentity< | ||
| + | |||
| + | // OK | ||
| + | using Ttrue = std::conditional_t< | ||
| + | // KO | ||
| + | //using Tfalse = std:: | ||
| </ | </ | ||
| - | ====Décorateur==== | + | |
| + | [[https:// | ||
| + | |||
| + | ====Exemples==== | ||
| + | |||
| + | ===Décorateur (spécialisation sur type)=== | ||
| [[https:// | [[https:// | ||
| - | * implicit return type | ||
| <code cpp> | <code cpp> | ||
| #include < | #include < | ||
| Ligne 122: | 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 183: | 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 251: | 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 315: | 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 |
| - | ====Divers==== | + | Il n'est pas possible de faire de la spécialisation partielle de template comme pour les classes. |
| - | ===Empêcher l'utilisation du template non spécialisé=== | + | * '' |
| - | '' | + | Il est possible d'activer certaines spécialisations de template en fonction du type. Mais c'est de la surcharge, pas de la spécialisation. Il faut bien vérifier que les '' |
| + | |||
| + | '' | ||
| <code cpp> | <code cpp> | ||
| #include < | #include < | ||
| - | template < | + | struct |
| - | struct | + | using R = int; |
| + | }; | ||
| - | // Template général. | + | struct F { |
| - | template <class T> | + | |
| - | T fun(T a) { | + | }; |
| - | | + | |
| - | static_assert(foobar< | + | |
| - | "this function has to be implemented for desired type"); | + | |
| - | } | + | |
| - | template <> | + | class A { |
| - | int fun(int a) { | + | |
| - | return | + | |
| - | } | + | |
| + | return | ||
| + | } | ||
| - | int main() { | + | template < |
| - | | + | |
| - | | + | return 27; |
| - | // fun<float>(10.14); // Echec | + | |
| - | } | + | }; |
| + | |||
| + | int main() { return A::f<I> | ||
| </ | </ | ||
| - | Autre exemple avec '' | + | * 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> | <code cpp> | ||
| - | # | + | template |
| - | + | struct A { | |
| - | struct A | + | |
| - | { | + | |
| - | using Ty = int; | + | |
| }; | }; | ||
| - | |||
| - | struct B {}; | ||
| - | |||
| - | // KO, should be OK. | ||
| - | // using Ttrue = std:: | ||
| - | // KO | ||
| - | // using Tfalse = std:: | ||
| template < | template < | ||
| - | struct | + | struct |
| - | { | + | |
| - | using type = T; | + | |
| }; | }; | ||
| - | |||
| - | template < | ||
| - | struct LazyLoadTy : LazyLoadIdentity< | ||
| - | |||
| - | // OK | ||
| - | using Ttrue = std:: | ||
| - | // KO | ||
| - | //using Tfalse = std:: | ||
| </ | </ | ||
| - | |||
| - | [[https:// | ||
| - | |||
lang/cpp/templatespecialisation.1625471470.txt.gz · Dernière modification : de root
