0Pricing
C++ Academy · Leçon

Spécialisation complète

Personnaliser les modèles pour un type

Spécialisation complète est une leçon C++ Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C++ Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C++ Academy comprend 4 leçons au total.

Récapitulatif : modèles

Un modèle permet à un même fragment de code de fonctionner avec de nombreux types. Le compilateur génère une version concrète pour chaque type utilisé.

  • La forme générale prend en charge tous les types.
  • Parfois, un type nécessite un traitement spécial.
#include <iostream>

template <typename T>
T maxOf(T a, T b) { return a > b ? a : b; }

int main() {
    std::cout << maxOf(3, 9) << ' ' << maxOf(2.5, 1.5) << '\n';
    return 0;
}

Qu'est-ce qu'une spécialisation complète ?

La spécialisation complète fournit une implémentation entièrement distincte pour un type précis, en remplaçant le modèle général uniquement pour ce type.

#include <iostream>

template <typename T>
void describe(T) { std::cout << "some type\n"; }

template <>
void describe(int) { std::cout << "an int\n"; }

int main() {
    describe(3.14);
    describe(42);
    return 0;
}

La syntaxe

Une spécialisation complète commence par des chevrons vides template <> et indique le type exact dans la spécialisation.

#include <iostream>

template <typename T>
struct TypeName { static const char* get() { return "unknown"; } };

template <>
struct TypeName<bool> { static const char* get() { return "bool"; } };

int main() {
    std::cout << TypeName<double>::get() << '\n';
    std::cout << TypeName<bool>::get() << '\n';
    return 0;
}

Spécialiser un modèle de classe

Des modèles de classe entiers peuvent être spécialisés, ce qui donne à un type ses propres membres et son propre comportement, distincts de ceux du modèle principal.

#include <iostream>

template <typename T>
struct Storage {
    T value;
    void show() { std::cout << "value: " << value << '\n'; }
};

template <>
struct Storage<bool> {
    bool value;
    void show() { std::cout << (value ? "true" : "false") << '\n'; }
};

int main() {
    Storage<int> s{5}; s.show();
    Storage<bool> b{true}; b.show();
    return 0;
}

Pourquoi spécialiser ?

La spécialisation prend en charge les types qui nécessitent une logique différente, par exemple const char*, qui nécessite une comparaison de chaînes plutôt qu'une comparaison de pointeurs.

#include <iostream>
#include <cstring>

template <typename T>
bool equal(T a, T b) { return a == b; }

template <>
bool equal(const char* a, const char* b) { return std::strcmp(a, b) == 0; }

int main() {
    std::cout << std::boolalpha;
    std::cout << equal(5, 5) << '\n';
    std::cout << equal("hi", "hi") << '\n';
    return 0;
}

Spécialiser un seul membre

Pour un modèle de classe, vous pouvez spécialiser une seule fonction membre pour un type donné tout en réutilisant le reste.

#include <iostream>

template <typename T>
struct Printer {
    void print(T v) { std::cout << v << '\n'; }
};

template <>
void Printer<char>::print(char v) {
    std::cout << "char: " << v << '\n';
}

int main() {
    Printer<int>{}.print(7);
    Printer<char>{}.print('A');
    return 0;
}

La correspondance l'emporte sur le général

Lorsqu'une spécialisation complète existe pour le type exact, le compilateur la préfère toujours au modèle principal.

#include <iostream>

template <typename T>
int rank() { return 0; }

template <>
int rank<double>() { return 99; }

int main() {
    std::cout << rank<int>() << ' ' << rank<double>() << '\n';
    return 0;
}

La spécialisation doit suivre le modèle principal

Une spécialisation doit être déclarée après que le modèle principal est devenu visible ; sinon, le compilateur n'a rien à spécialiser.

#include <iostream>

template <typename T>
const char* kind() { return "generic"; }

template <>
const char* kind<float>() { return "float"; }

int main() {
    std::cout << kind<int>() << ' ' << kind<float>() << '\n';
    return 0;
}

Spécialiser des modèles de la bibliothèque standard

Vous pouvez spécialiser certains modèles de la bibliothèque standard, comme std::hash, pour vos propres types afin qu'ils fonctionnent avec des conteneurs hachés.

#include <iostream>

struct Point { int x, y; };

template <typename T>
struct Hasher { size_t operator()(const T&) { return 0; } };

template <>
struct Hasher<Point> {
    size_t operator()(const Point& p) { return p.x * 31 + p.y; }
};

int main() {
    Hasher<Point> h;
    std::cout << h(Point{2, 3}) << '\n';
    return 0;
}

Spécialisation de valeur

Les paramètres de modèle non typés peuvent être spécialisés pour des valeurs précises, ce qui est utile pour les tables produites à la compilation.

#include <iostream>

template <int N>
struct Fib { static const int value = Fib<N-1>::value + Fib<N-2>::value; };

template <>
struct Fib<0> { static const int value = 0; };

template <>
struct Fib<1> { static const int value = 1; };

int main() {
    std::cout << Fib<10>::value << '\n';
    return 0;
}

Conserver un comportement cohérent

Une spécialisation doit conserver le même contrat conceptuel que le modèle principal ; seule l’implémentation change. Sinon, le code appelant risque d’être surpris.

#include <iostream>

template <typename T>
T zero() { return T{}; }

template <>
int zero<int>() { return 0; }

int main() {
    std::cout << zero<int>() << ' ' << zero<double>() << '\n';
    return 0;
}

Vérification rapide

Vérifiez votre compréhension de la syntaxe de spécialisation complète.

Récapitulatif

Vous avez découvert la spécialisation complète :

  • elle fournit une implémentation dédiée pour un type précis
  • elle s’écrit avec template <> et le type concret
  • le compilateur privilégie toujours une spécialisation exacte
  • elle fonctionne pour les fonctions, les classes, les membres individuels et les valeurs précises

Vous allez maintenant découvrir la spécialisation partielle, qui correspond à des motifs de types.

Questions Fréquemment Posées

La leçon « Spécialisation complète » est-elle gratuite ?

Oui — le texte complet de « Spécialisation complète » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C++ Academy, passe à CoddyKit PRO. Le cours C++ Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Spécialisation complète » ?

Personnaliser les modèles pour un type Tu pratiques C++ Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C++ Academy ?

Aucune expérience préalable n'est requise. C++ Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Spécialisation complète » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C++ Academy ?

Oui. Chaque leçon C++ Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Spécialisation complète
  2. Spécialisation partielle
  3. SFINAE
  4. Schémas avec enable_if
← Retour à C++ Academy