C++ Academy · Leçon

Schémas avec enable_if

Contraindre les modèles selon l’approche classique

Leçon 4 sur 413 étapes

Schémas avec enable_if est une leçon C++ Academy gratuite sur CoddyKit. Ceci est la leçon 4 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.

Qu’est-ce que enable_if ?

std::enable_if est un petit trait qui définit conditionnellement un membre type. Lorsque sa condition est vraie, le type existe ; lorsqu’elle est fausse, le modèle environnant est retiré par SFINAE.

  • Il se trouve dans <type_traits>.
  • C’est l’outil classique pour restreindre les modèles.
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
doubleIt(T v) { return v * 2; }

int main() {
    std::cout << doubleIt(21) << '\n';
    return 0;
}

Fonctionnement

enable_if<Cond, T>::type est égal à T uniquement lorsque Cond est vrai. Si Cond est faux, aucun membre type n’existe et la substitution échoue.

#include <iostream>
#include <type_traits>

int main() {
    std::cout << std::boolalpha;
    std::cout << std::is_same<std::enable_if<true, int>::type, int>::value << '\n';
    return 0;
}

enable_if dans le type de retour

Le placement le plus courant est le type de retour. La fonction n’existe que lorsque la condition est satisfaite.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
half(T v) { return v / 2; }

int main() {
    std::cout << half(5.0) << '\n';
    return 0;
}

enable_if comme paramètre de modèle

Une autre forme courante place enable_if dans un paramètre de modèle par défaut, ce qui laisse le type de retour propre.

#include <iostream>
#include <type_traits>

template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
T triple(T v) { return v * 3; }

int main() {
    std::cout << triple(4) << '\n';
    return 0;
}

Raccourci enable_if_t

C++14 a ajouté l’alias std::enable_if_t<Cond, T>, qui vous permet d’éviter la syntaxe typename ...::type superflue.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
negate(T v) { return -v; }

int main() {
    std::cout << negate(8) << '\n';
    return 0;
}

Associer deux surcharges

Définissez des conditions complémentaires afin qu’exactement une surcharge soit valide pour chaque type, sans ambiguïté.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, const char*>
category() { return "integer"; }

template <typename T>
std::enable_if_t<!std::is_integral<T>::value, const char*>
category() { return "non-integer"; }

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

Combiner des conditions

Utilisez des opérateurs logiques sur les valeurs des traits pour exprimer des contraintes plus riches, comme « entier et signé ».

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, T>
magnitude(T v) { return v < 0 ? -v : v; }

int main() {
    std::cout << magnitude(-12) << '\n';
    return 0;
}

Restreindre un constructeur

Vous pouvez placer enable_if sur le paramètre de modèle d’un constructeur afin de ne l’autoriser que pour les types compatibles.

#include <iostream>
#include <type_traits>

struct Wrapper {
    int value;
    template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
    Wrapper(T v) : value(static_cast<int>(v)) {}
};

int main() {
    Wrapper w(42);
    std::cout << w.value << '\n';
    return 0;
}

Piège des arguments de modèle par défaut

Deux surcharges qui ne diffèrent que par un paramètre de modèle enable_if par défaut sont considérées comme des redéfinitions. Donnez-leur des formes différentes, par exemple en plaçant une condition sur le type de retour.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
printKind() { std::cout << "int\n"; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
printKind() { std::cout << "float\n"; }

int main() {
    printKind<int>();
    printKind<double>();
    return 0;
}

Comparaison avec les concepts

En C++20, les concepts remplacent la plupart des utilisations de enable_if avec une syntaxe beaucoup plus claire, mais enable_if reste essentiel pour le code antérieur à C++20 et certains cas particuliers.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T>
square(T v) { return v * v; }

int main() {
    std::cout << square(6) << ' ' << square(1.5) << '\n';
    return 0;
}

Un exemple complet

Combinez tous les éléments : une famille de fonctions qui formate différemment les entiers et les nombres flottants, avec une sélection effectuée à la compilation.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
format(T v) { std::cout << "int[" << v << "]\n"; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
format(T v) { std::cout << "float(" << v << ")\n"; }

int main() {
    format(10);
    format(3.5);
    return 0;
}

Vérification rapide

Vérifiez votre compréhension de enable_if.

Récapitulatif

Vous avez découvert les motifs classiques utilisant enable_if :

  • il définit ::type uniquement lorsque la condition est vraie, ce qui permet SFINAE
  • il se place dans le type de retour ou dans un paramètre de modèle par défaut
  • utilisez l’alias enable_if_t et combinez les traits avec des opérateurs logiques
  • les concepts le remplacent en C++20, mais il reste largement utilisé

Le cours sur la spécialisation des modèles et SFINAE est maintenant terminé.

Gratuit pour commencer

Apprends C++ avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
51
Leçons
203

Questions Fréquemment Posées

La leçon « Schémas avec enable_if » est-elle gratuite ?

Oui — le texte complet de « Schémas avec enable_if » 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 « Schémas avec enable_if » ?

Contraindre les modèles selon l’approche classique 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 4 sur 4.

Combien de temps prend la leçon « Schémas avec enable_if » ?

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