enable_if: cas de la méthode de matrice d'une base de modèle hérité plusieurs fois
Question
Si j'ai une classe de base de modèle avec une méthode de modèle:
template <typename T>
class S
{
public:
template <typename U>
void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0)
{
std::cout << p << std::endl;
}
};
Pour l'exemple, je simplifie la méthode: il doit « existe » que si T == U
Si A est cette classe:
class A : public S<int> {};
Ensuite, je dois ce que je veux:
int i = 1;
A a;
a.f(i);
compiles, mais
double d = 2.0;
a.f(d);
ne compile pas: erreur: aucune fonction de mise en correspondance pour l'appel à « A :: f (double et) » Il est le comportement attendu.
Maintenant, nous allons A Hériter de S<double>
aussi:
class A : public S<int>, public S<double> {};
Ensuite, le code suivant ne compile pas:
int i = 1;
A a;
a.f(i);
error: request for member ‘f’ is ambiguous error: candidates are: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = double] error: template<class U> void S::f(U, typename boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T = int]
Je prévu il n'y a pas d'ambiguïté: f<int>
existe uniquement pour S<int>
Dans l'erreur du compilateur, nous pouvons remarquer que T est connu lorsque ce morceau de code est compilé, mais pas U (U = U).
Toute explication ou "contournement"?
La solution
Essayez ceci:
a.S<int>::f(i);
... ou bien injecter la fonction dans A
, par exemple.
class A : public S<int>, public S<double>
{
public:
using S<int>::f;
using S<double>::f;
};
Autres conseils
Vous avez raison, il existe uniquement dans S, mais deux fois. Une fois pour chaque type, int et double. Donc, dans votre cas, vous devrez spécifier exactement quelle fonction vous voulez appeler. La solution de Nim fonctionne comme ça.
D'autres ont donné de bons solutions de contournement, mais je veux répondre à cette autre question que vous avez
Je prévu il n'y a pas d'ambiguïté:.
f<int>
existe seulement pourS<int>
Vous avez dit a.f(i)
donc il faut d'abord chercher le nom f
dans A
. Il trouve deux f
s. Dans S<int>
et S<double>
. À l'époque de nom, il ne sait pas encore qu'il pourrait plus tard avoir S<int>::f
seulement choisi comme gagnant parce S<double>::f
serait jeté par SFINAE. La séparation claire de la recherche de nom et de la résolution de surcharge et de la déduction des arguments de modèle ne permet pas un tel entremêlement.