std::enable_if : paramètre vs paramètre de modèle
Je suis en train de construire une entrée vérificateur doit avoir des fonctions spécifiques pour l'entier et/ou double (par exemple "isPrime" devrait être disponible uniquement pour les entiers).
Si je suis en utilisant enable_if
comme un paramètre il fonctionne parfaitement :
template <class T>
class check
{
public:
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0)
{
return BuffCheck.getInt();
}
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0)
{
return BuffCheck.getDouble();
}
};
mais si je suis en utilisant comme modèle paramater (tel que démontré sur http://en.cppreference.com/w/cpp/types/enable_if )
template <class T>
class check
{
public:
template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type >
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type >
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
alors que j'ai l'erreur suivante :
error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded
error: with ‘template<class T> template<class U, class> static U check::readVal()’
Je ne peux pas comprendre ce qui est mauvais dans la deuxième version.
- Probablement pas pertinentes, mais dans VS2010 je ne peux pas le faire parce que le modèle par défaut, les arguments sont autorisés uniquement pour les modèles de classe - je ne sais pas à propos de g++
- C'est pédant, mais le
inline
mot clé sur un membre de méthode ou modèle n'est pas nécessaire, et certainement pas un membre qui est également un modèle 😉
Vous devez vous connecter pour publier un commentaire.
Modèle par défaut arguments ne font pas partie de la signature d'un modèle (donc les deux définitions d'essayer de définir le même modèle à deux reprises). Leurs types de paramètres sont partie de la signature, cependant. Ainsi, vous pouvez faire
= 0
j'ai écrit ne sert qu'à la prise de l'utilisateur de ne pas passer le0
lui-même (sinon, vous pouvez aussi écrire...
au lieu de= 0
, qui sera également pas besoin d'arguments, mais vide par défaut pack. Je considère que l'obscur toi et j'aime l'int de mieux en mieux). Il n'est pas nécessaire intrinsèquement pour la SFINAE de travail. Il est également= 0
dans les deux cas, donc si il serait une partie de la signature, il ne serait pas utile de distinguer, dans mon exemple de toute façon =)Le problème est que le compilateur voit 2 surcharges de la même méthode, à la fois, qui contiennent les mêmes arguments(aucun, dans ce cas) et la même valeur de retour. Vous ne pouvez pas fournir une telle définition. La façon la plus propre de le faire est d'utiliser SFINAE sur la valeur renvoyée de la fonction:
De cette façon, vous êtes offrant 2 différentes surcharges. On renvoie un int, l'autre renvoie un double, et un seul peut être instancié en utilisant un certain T.
Je sais que cette question est à propos de
std::enable_if
, cependant, je tiens à fournir une solution alternative pour résoudre le même problème sans enable_if. Il n'exigent C++17Ce code a l'air plus que si vous l'écrire au moment de l'exécution. Toutes les branches doivent être syntaxique correcte, mais la sémantique n'avez pas à être. Dans ce cas, si T est de type int, la getDouble n'est pas causant des erreurs de compilation (ou mises en garde) car il ne veut pas se contrôler et/ou utilisées par le compilateur.
Si le type de retour de la fonction serait de complexe de mentionner, vous pouvez toujours utiliser
auto
comme type de retour.