Maison >développement back-end >C++ >Comment sélectionner une fonction membre en fonction d'un paramètre de modèle à l'aide de « enable_if » ?

Comment sélectionner une fonction membre en fonction d'un paramètre de modèle à l'aide de « enable_if » ?

DDD
DDDoriginal
2024-10-25 19:06:39845parcourir

How to Select a Member Function Based on a Template Parameter Using `enable_if`?

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn