Sélection d'une fonction membre à l'aide des conditions Enable_If
La tâche consiste à déterminer l'invocation d'une fonction membre en fonction d'un paramètre de modèle de classe. L'extrait de code suivant tente d'y parvenir :
<code class="cpp">#include <iostream> #include <type_traits> template<typename T> struct Point { void MyFunction(typename std::enable_if<std::is_same<T, int>::value, T &>::type* = 0) { std::cout << "T is int." << std::endl; } void MyFunction(typename std::enable_if<!std::is_same<T, int>::value, float &>::type* = 0) { std::cout << "T is not int." << std::endl; } };</code>
Cependant, ce code ne parvient pas à se compiler avec l'erreur "aucun type nommé 'type' dans 'struct std::enable_if'".
SFINAE en action
La clé pour comprendre ce problème réside dans le concept de l'échec de la substitution n'est pas une erreur (SFINAE). Enable_if permet une compilation conditionnelle basée sur des arguments de modèle. Dans ce cas, l'argument du modèle T est déjà connu lorsque les fonctions membres sont instanciées. Par conséquent, la condition est évaluée au moment de l'instanciation et la fonction correspondante est sélectionnée.
Fixation du code
Pour rectifier cela, nous devons introduire un argument de modèle factice qui est par défaut T. Cela permet au mécanisme SFINAE de fonctionner comme prévu. Le code modifié ressemblerait à ceci :
<code class="cpp">template<typename T> struct Point { template<typename U = T> typename std::enable_if<std::is_same<U, int>::value>::type MyFunction() { std::cout << "T is int." << std::endl; } template<typename U = T> typename std::enable_if<std::is_same<U, float>::value>::type MyFunction() { std::cout << "T is not int." << std::endl; } };</code>
Empêcher la spécialisation explicite des fonctions membres
Comme l'a souligné HostileFork, le code d'origine permet la spécification explicite des arguments du modèle pour les fonctions membres, ce qui pourrait conduire à des résultats incorrects. Pour éviter cela, nous pouvons ajouter un static_assert qui vérifie si des arguments de modèle sont fournis. Cela garantit que la fonction membre correcte est toujours invoquée en fonction de l'argument du modèle T. Le code modifié serait :
<code class="cpp">template<typename T> struct Point { template<typename... Dummy, typename U = T> typename std::enable_if<std::is_same<U, int>::value>::type MyFunction() { static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!"); std::cout << "T is int." << std::endl; } template<typename... Dummy, typename U = T> typename std::enable_if<std::is_same<U, float>::value>::type MyFunction() { static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!"); std::cout << "T is not int." << std::endl; } };</code>
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!