2012-09-24 9 views
5

Dado el siguiente código:Moving Método Plantilla de saltos derivados Compilación

template<typename T> 
class A 
{ 
public: 
    T t; 
}; 

class B 
{ 
public: 
    void foo(int i) {} 

    template<typename T> 
    void foo(A<T>& a) {} 
}; 

int main() 
{ 
    A<int> a; 
    B  b; 

    b.foo(a ); 
    b.foo(a.t); 
} 

Esto compila y funciona bien; las versiones correctas sobrecargadas de B::foo() se eligen y llaman para a y a.t.

Ahora les presento una nueva clase que deriva de CB y mover la versión de la plantilla de ::foo() de B y en C:

template<typename T> 
class A 
{ 
public: 
    T t; 
}; 

class B 
{ 
public: 
    void foo(int i) {} 
}; 

class C: public B 
{ 
public: 
    template<typename T> 
    void foo(A<T>& a) {} 
}; 

int main() 
{ 
    A<int> a; 
    C  c; 

    c.foo(a ); // Fine 
    c.foo(a.t); // Error 
} 

Y ahora el código no se compilará más. Visual Studio 2005 está declarando:

error C2784: 'void C::foo(A<T> &)' : could not deduce template argument for 'A<T> &' from 'int' 

De hecho, llamando C::foo() con cualquier int resultados de valor en este error. Casi parece que la sobrecarga de la plantilla está ocultando la sobrecarga del método int.

¿Por qué sucede esto? ¿Hay algún problema con el compilador de Visual Studio 2005? Desafortunadamente, no puedo probarlo en ningún otro compilador en este momento.

Se agradece cualquier información.

Respuesta

5

Casi parece que la sobrecarga del método para int está siendo ocultada por la sobrecarga de plantilla.

¡Exactamente! Es necesario añadir una declaración using a la clase C:

class C: public B 
{ 
public: 
    using B::foo; 
    template<typename T> 
    void foo(A<T>& a) {} 
}; 

Cuando se declara una función miembro de una clase derivada, todas las funciones miembro de la clase base con el mismo nombre están ocultos. Ver §3.3.10/3 de la norma ISO/IEC 14882: 2011:

La declaración de un miembro en una clase derivada (Cláusula 10) oculta la declaración de un miembro de una clase base del mismo nombre; ver 10.2.

2

Se está ocultando, sin sobrecargar. Utilice

class C: public B 
{ 
public: 
    using B::foo; 
    template<typename T> 
    void foo(A<T>& a) {} 
}; 
1

Correcto, la función de base es oculto. Ese es realmente el término adecuado para eso. Agregue using B::foo; a la definición de clase de C para mostrarlo.

Cuestiones relacionadas