2011-01-28 11 views
8

puedo compilar el código con GCC (4.2.1 de Apple construir 5664)ambigua definición del operador() con la herencia múltiple

#include <cstddef> 

using std::size_t; 

template <char I> struct index { }; 

struct a 
{ 
    void operator()(size_t const &) { } 
}; 

struct b 
{ 
    template <char I> 
    void operator()(index<I> const &) { } 
}; 

struct c: public a, public b { }; 

int main (int argc, char const *argv[]) 
{ 
    c vc; 
    vc(1); 

    return 0; 
} 

y me da el siguiente error:

main.cpp: In function ‘int main(int, const char**)’: 
main.cpp:22: error: request for member ‘operator()’ is ambiguous 
main.cpp:14: error: candidates are: template<char I> void b::operator()(const index<I>&) 
main.cpp:9: error:     void a::operator()(const size_t&) 

I don' entiendo la razón por la cual este código es ambiguo; los dos métodos tienen diferentes firmas.

+0

me sorprende que Clang puede compilar el código, mientras que GCC se queja. – peoro

Respuesta

6

Modificar c esta manera:

struct c: public a, public b 
{ 
    using a::operator(); 
    using b::operator(); 
}; 

C++ (antes C++ 0x) es una especie de torpe en heredar funciones: si proporciona una función con el mismo nombre de una función de clase base se esconde los de la clase base.

Parece que heredar de dos clases tiene el mismo problema.

// busca de la norma ...

+0

Eso es solo el caso si tienen la misma firma, que estas funciones no tienen. –

+0

@Zac Howland: no estoy seguro, podría estar en lo cierto, pero GCC no lo compilará de lo contrario. Tal vez un error GCC? Clang compilará sin problema el código de OP ... – peoro

+5

@Zac Howland: el ocultamiento ocurre en la coincidencia de nombre, no en la firma. –

1

Es ambiguo porque está pasando en una constante entera que puede (presumiblemente) ser convertida a std::size_t o index tipos. Cambiar main a la siguiente y debe resolverlo:

int main (int argc, char const *argv[]) 
{ 
    c vc; 
    vc(static_cast<std::size_t>(1)); 

    return 0; 
} 

Dicho esto, es muy probable que no se debe utilizar la herencia múltiple aquí.

+1

Un entero no se puede convertir a un tipo de índice. Y si intentas compilar, no funciona. –

+0

@mattia: Deberás ser más específico sobre el problema. Con lo que has mostrado, el código anterior funcionará (obviamente, tendrás que cambiar el modelo si quieres al otro operador). @ peoro: 'static_cast' hace exactamente lo que está haciendo aquí, convirtiendo un entero en un tipo específico. –

+0

@mattia: intente hacer esto en lugar del 'static_cast' en línea y luego:' std :: size_t i = 1; vc (i); ' –

6

La resolución de nombres se realiza antes de la resolución de sobrecarga.
No hay operator() en c por lo que el compilador busca operator() en sus clases base y encuentra uno en a y otro en b haciendo que el nombre sea ambiguo (y no se produce una resolución de sobrecarga).

Si desea eliminar el nombre de la ambigüedad puede llamar a::operator() explícitamente: vc.a::operator()(1);