Les types génériques offrent la possibilité de créer des classes ou des fonctions pouvant fonctionner sur un large éventail de types de données. Toutefois, dans certains cas, vous souhaiterez peut-être restreindre un type générique pour n'accepter que certains types. C'est là que le concept de contrainte des types génériques entre en jeu.
En Java, vous pouvez utiliser le mot-clé extends pour contraindre une classe générique à n'accepter que les types qui étendent une classe spécifique. C ne possède pas d'équivalent direct à ce mot-clé. Cependant, plusieurs approches peuvent être utilisées pour obtenir des résultats similaires.
C 11 introduit
#include <type_traits> template<typename T> class ObservableList { static_assert(std::is_base_of<list, T>::value, "T must inherit from list"); // code here... };
Cette approche vérifie que le type T hérite de la liste avant d'autoriser son utilisation dans ObservableList. .
Une approche alternative consiste à s'appuyer sur le typage Duck, ce qui implique de vérifier si un type fournit des méthodes ou des fonctions spécifiques sans nécessairement hériter d’une classe de base. Cette approche implique moins de restrictions mais peut conduire à des erreurs potentielles si les types n'adhèrent pas à l'interface attendue.
Une autre option consiste à définir des traits personnalisés pour contraindre les types. Les traits sont des classes ou des structures qui fournissent un ensemble de modèles de fonctions pour tester diverses propriétés de type. En définissant des traits personnalisés, vous pouvez spécifier les exigences relatives aux types pouvant être utilisés avec votre type générique.
#include <type_traits> template<typename T> struct HasConstIterator : std::false_type {}; template<typename T> struct HasConstIterator<T, Void<typename T::const_iterator>> : std::true_type {}; struct HasBeginEnd { template<typename T> static std::true_type Test(int); template<typename...> static std::false_type Test(...); }; template<typename T> class ObservableList { static_assert(HasConstIterator<T>::value, "Must have a const_iterator typedef"); static_assert(HasBeginEnd<T>::value, "Must have begin and end member functions"); // code here... };
Cet exemple montre l'utilisation de traits personnalisés implémentés à l'aide de techniques de métaprogrammation pour contraindre le type T à répondre à des caractéristiques spécifiques. exigences d'interface.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!