Outils pour utilisateurs

Outils du site


lang:cpp:template

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
lang:cpp:template [2021/07/05 09:55] – Ajout de "Auto déduction" pour le retour d'une fonction rootlang:cpp:template [2025/02/05 10:07] (Version actuelle) – [const Args...] : fix typo root
Ligne 6: Ligne 6:
  
 <code cpp> <code cpp>
-template<typename R>+typename<template R>
 R fonction() R fonction()
 { {
Ligne 21: Ligne 21:
 } }
 </code> </code>
 +
 +====const Args...====
 +
 +Il faut éviter les ''const'' sur les templates variadiques.
 +
 +Sinon, cela impose l'utilise de const partout et ainsi, le code ci-dessous devient invalide (même s'il compile quand même) car le compilateur passe le nombre en tant que ''double'' et non ''const double''.
 +
 +<code cpp>
 +template<typename ...Args>
 +void f(const Args&&... args){}
 +
 +f(1.2);
 +</code>
 +
 +J'ai déjà eu des codes plus complexes où cela posait problème.
  
 =====Héritage===== =====Héritage=====
Ligne 291: Ligne 306:
  
 ====Séparer le code source des fonctions et leur définition dans une classe template==== ====Séparer le code source des fonctions et leur définition dans une classe template====
 +
 +  * Exemple avec une classe template
 +
 C'est possible de ne pas être obligé de rendre ''inline'' toutes les méthodes d'une classe ''template''. Mais il faut alors explicitement indiquer quelles combinaisons ''class'' / ''template'' seront utilisées par un ''template class XX<YY>;'' C'est possible de ne pas être obligé de rendre ''inline'' toutes les méthodes d'une classe ''template''. Mais il faut alors explicitement indiquer quelles combinaisons ''class'' / ''template'' seront utilisées par un ''template class XX<YY>;''
  
Ligne 310: Ligne 328:
 void T<X>::fff() {} void T<X>::fff() {}
  
 +// On instancie uniquement T<int> (et donc T<int>::fff()).
 template class T<int>; template class T<int>;
 </file> </file>
Ligne 319: Ligne 338:
 <file cpp main.cc> <file cpp main.cc>
 #include "template.h" #include "template.h"
- 
-extern template class T<int>(); 
  
 int main() int main()
 { {
   T<int> tint;   T<int> tint;
-  return tint.retval();+  return tint.fff();
 } }
 </file> </file>
  
 +  * Exemple avec une fonction template
 +
 +<file cpp file.h>
 +class A {
 +    template<typename U>
 +    void f();
 +};
 +</file>
 +
 +<file cpp file.cpp>
 +template<typename U> void A::f(){}
 +
 +// Instanciation pour U=int
 +template void A::f<int>();
 +
 +// Spécialisation pour U=double
 +template<> void A::f<double>(){}
 +</file>
 +
 +  * Exemple avec une fonction template dans une classe template
 +
 +<file cpp file.h>
 +template<typename T>
 +class A {
 +    template<typename U>
 +    void f(U u);
 +};
 +</file>
 +
 +<file cpp file.cpp>
 +template<typename T> template<typename U> void A<T>::f(U u){}
 +
 +template void A<int>::f(short u);
 +</file>
 +
 +  * Messages d'erreur
 +
 +''error: specialization of XXX after instantiation''
 +
 +''error: explicit specialization of XXX after instantiation''
 +
 +''error C2908: explicit specialization; XXX has already been instantiated''
 +
 +Il ne faut pas utiliser une classe spécialisée avant qu'elle ne soit définie.
 +
 +<code cpp>
 +template <typename T>
 +class A {};
 +
 +// Doit être défini après la spécialisation.
 +A<int> a;
 +
 +template <>
 +class A<int> {};
 +</code>
 ====Afficher en string le type template==== ====Afficher en string le type template====
 <code cpp> <code cpp>
Ligne 490: Ligne 562:
  
   AA2<Types>::ff();   AA2<Types>::ff();
 +}
 +</code>
 +
 +====Sérialisation====
 +
 +Compter le nombre de champ d'une classe.
 +
 +<code cpp>
 +#include <iostream>
 +
 +struct UniversalType {
 +    template <typename T>
 +    operator T();  // no definition required
 +};
 +
 +template <typename T, typename... A0>
 +consteval auto MemberCounter(auto... c0) {
 +    if constexpr (requires { T{{A0{}}..., {UniversalType{}}, c0...}; })
 +        return MemberCounter<T, A0..., UniversalType>(c0...);
 +    else if constexpr (
 +        requires {
 +            T{{A0{}}..., {UniversalType{}}, c0...};
 +        } ||
 +        requires {
 +            T{{A0{}}..., c0..., UniversalType{}};
 +        })
 +        return MemberCounter<T, A0...>(c0..., UniversalType{});
 +    return sizeof...(A0) + sizeof...(c0);
 +}
 +
 +int main() {
 +    using TestType = struct {
 +        int x[3];
 +        float y;
 +        char z;
 +    };
 +    auto [a, b, c] = TestType{};                          // decomposes into 3
 +    std::cout << MemberCounter<TestType>() << std::endl;  // prints 3
 } }
 </code> </code>
Ligne 496: Ligne 606:
  
   * Il manque un mot clé ''typename''   * Il manque un mot clé ''typename''
 +
 +Il faut parfois rajouter le mot clé ''typename'' quand un type est suivi du symbole ''<''. Cela permet au compilateur de différentier l'opérateur de comparaison ''<'' avec le symbole permettant d'explicité un type dans un template.
  
 <code cpp> <code cpp>
Ligne 522: Ligne 634:
       retval->impl_ = impl_->f<Action, U...>(std::forward<const Args>(args)...);       retval->impl_ = impl_->f<Action, U...>(std::forward<const Args>(args)...);
       ^                                ~       ^                                ~
 +</code>
 +
 +ou encore
 +
 +<code cpp>
 +error: expected primary-expression before ')' token
 +    return this->deco_->f<123, 456>();
 +                                           ^
 </code> </code>
  
Ligne 530: Ligne 650:
 </code> </code>
  
 +===Mapping d'un type vers un autre via une map===
 +
 +https://stackoverflow.com/questions/68668956/c-how-to-implement-a-compile-time-mapping-from-types-to-types
 +
 +<code>
 +using my_map = type_map<
 +    pair<int, float>,
 +    pair<char, double>,
 +    pair<long, short>
 +>;
 +
 +static_assert(std::is_same_v<my_map::find<int>, float>);
 +static_assert(std::is_same_v<my_map::find<char>, double>);
 +static_assert(std::is_same_v<my_map::find<long>, short>);
 +</code>
 +
 +<code cpp>
 +template <typename T>
 +struct type_tag
 +{
 +  using type = T;
 +};
 +
 +template <typename K, typename V>
 +struct pair
 +{
 +  using first_type = K;
 +  using second_type = V;
 +};
 +
 +template <typename Pair>
 +struct element
 +{
 +  static auto value(type_tag<typename Pair::first_type>)
 +      -> type_tag<typename Pair::second_type>;
 +};
 +
 +template <typename... elems>
 +struct type_map : element<elems>...
 +{
 +  using element<elems>::value...;
 +
 +  template <typename K>
 +  using find = typename decltype(type_map::value(type_tag<K>{}))::type;
 +};
 +</code>
lang/cpp/template.1625471757.txt.gz · Dernière modification : 2021/07/05 09:55 de root