2010-04-26 13 views
8

En Visual Studio 2008, el compilador no puede resolver la llamada a SetCustomer en _tmain a continuación y que sea inequívoco:acceso ambiguo a la función miembro de plantilla de clase base

template <typename TConsumer> 
struct Producer 
{ 
    void SetConsumer(TConsumer* consumer) { consumer_ = consumer; } 

    TConsumer* consumer_; 
}; 

struct AppleConsumer 
{ 
}; 

struct MeatConsumer 
{ 
}; 

struct ShillyShallyProducer : public Producer<AppleConsumer>, 
           public Producer<MeatConsumer> 
{ 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ShillyShallyProducer producer; 
    AppleConsumer consumer; 
    producer.SetConsumer(&consumer); // <--- Ambiguous call!! 

    return 0; 
} 

Este es el error de compilación:

// error C2385: ambiguous access of 'SetConsumer' 
// could be the 'SetConsumer' in base 'Producer<AppleConsumer>' 
// or could be the 'SetConsumer' in base 'Producer<MeatConsumer>' 

Pensé que el mecanismo de búsqueda de argumentos de la plantilla sería lo suficientemente inteligente como para deducir la base correcta Producer. ¿Por qué no?

que podría conseguir esto, cambiando Producer a

template <typename TConsumer> 
struct Producer 
{ 
    template <typename TConsumer2> 
    void SetConsumer(TConsumer2* consumer) { consumer_ = consumer; } 

    TConsumer* consumer_; 
}; 

y llame SetConsumer como

producer.SetConsumer<AppleConsumer>(&consumer); // Unambiguous call!! 

pero sería mejor si yo no tuviera que ...

+0

que acababa de señalar que en la solución propuesta, no necesita llamar a 'SetConsumer (& consumer)', 'SetConsumer (& consumer)' será suficiente (y deducirá correctamente el argumento de la plantilla). – sbk

+0

@sbk: No, no lo hará. Intenté eso antes de publicar, y ahora una vez más para estar seguro. Aún ambiguo. –

Respuesta

12

I thought the template argument lookup mechanism would be smart enough to deduce the correct base Producer.

Esto no tiene que ver con las plantillas, que proviene del uso de múltiples clases base - la búsqueda de nombre ya es ambigua y la resolución de sobrecarga sólo toma colocar después de eso.

Un ejemplo simplificado sería el siguiente:

struct A { void f() {} }; 
struct B { void f(int) {} }; 
struct C : A, B {}; 

C c; 
c.f(1); // ambiguous 

Soluciones provisionales están calificando explícitamente la llamada o para introducir las funciones en las clases alcance derivado:

struct ShillyShallyProducer : public Producer<AppleConsumer>, 
           public Producer<MeatConsumer> 
{ 
    using Producer<AppleConsumer>::SetConsumer; 
    using Producer<MeatConsumer >::SetConsumer; 
}; 
+0

@gf: "introducir las funciones en el alcance de las clases derivadas": es una gran solución, ya que no quiero cambiar los sitios de llamadas de los clientes productores cada vez que agrego un nuevo producto producido. Encantador, ¡gracias! –

2

Puedes simplemente usar la calificación explícita en tu llamada a la función. En lugar de:

producer.SetConsumer(&consumer); 

intento:

producer.Producer<AppleConsumer>::SetConsumer(&consumer); 
Cuestiones relacionadas