enable_if: caso de método plantado de una base de plantilla heredada varias veces
Pregunta
Si tengo una clase base de plantilla con un método de plantilla:
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;
}
};
Para el ejemplo, simplifico el método: debe "existe" solo si t == u
Si a es esta clase:
class A : public S<int> {};
Entonces tengo lo que quiero:
int i = 1;
A a;
a.f(i);
compilación, pero
double d = 2.0;
a.f(d);
No compila: Error: no hay función coincidente para la llamada a 'A :: F (Double &)' Es el comportamiento esperado.
Ahora hemos herido de S<double>
además :
class A : public S<int>, public S<double> {};
Entonces el siguiente código no compila:
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]
Esperaba que no hubiera ambigüedad: f<int>
existe solo para S<int>
En el error del compilador, podemos notar que T se sabe cuando se compila esta pieza de código, pero no u (u = u).
¿Alguna explicación o "solución alternativa"?
Solución
Prueba esto:
a.S<int>::f(i);
... o alternativamente inyectar la función en A
, p.ej
class A : public S<int>, public S<double>
{
public:
using S<int>::f;
using S<double>::f;
};
Otros consejos
Tienes razón, solo existe en S, pero dos veces. Una vez para cada tipo, int y duplicar. Entonces, en su caso, deberá especificar exactamente a qué función desea llamar. La solución de NIM funciona así.
Otros han dado buenas soluciones, pero quiero responder a esa otra pregunta que tenía
Esperaba que no hubiera ambigüedad:
f<int>
existe solo paraS<int>
.
Usted dijo a.f(i)
Entonces primero debe buscar el nombre f
en A
. Encuentra dos f
s. En S<int>
y S<double>
. En el tiempo de búsqueda de nombre, aún no sabe que más tarde solo podría haber seleccionado S<int>::f
como ganador porque S<double>::f
sería tirado por Sfinae. La clara separación de la búsqueda de nombre y la resolución de sobrecarga y la deducción de argumentos de plantilla no permite tal entremezcla.