2011-01-28 18 views
8

compilo questo codice con GCC (4.2.1 di Apple di costruire 5664)ambiguo definizione di operatore() con l'ereditarietà multipla

#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; 
} 

e mi danno il seguente errore:

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' t comprendere il motivo per cui questo codice è ambiguo; i due metodi hanno diverse firme.

+0

Sono sorpreso che Clang può compilare il codice, mentre GCC si lamenta. – peoro

risposta

6

Modifica c questo modo:

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

C++ (prima C++ 0x) è una specie di imbarazzante nelle funzioni ereditare: se si forniscono una funzione con lo stesso nome di una funzione classe base nasconde quelli di classe base.

Sembra che anche ereditare da due classi abbia lo stesso problema.

// alla ricerca per lo standard ...

+0

Questo è solo il caso se hanno la stessa firma, che queste funzioni non hanno. –

+0

@Zac Howland: non è sicuro, potresti avere ragione, ma GCC non lo compilerà diversamente. Forse un bug GCC? Clang compilerà senza alcun codice di errore OP ... – peoro

+5

@Zac Howland: nascondersi accade sul nome match non firma. –

1

È ambiguo perché si sta passando una costante intera che può (presumibilmente) essere convertita in un tipo std::size_t o index. Cambiare main al seguente e deve risolverla:

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

    return 0; 
} 

Detto questo, è molto probabile che non si dovrebbe usare l'ereditarietà multipla qui.

+1

Un numero intero non può essere convertito in un tipo di indice. E se provi a compilare, non funziona. –

+0

@mattia: Dovrai essere più specifico riguardo al problema. Con quello che hai mostrato, il codice sopra funzionerà (ovviamente, dovresti cambiare il cast se vuoi l'altro operatore). @peoro: 'static_cast' fa esattamente ciò che sta facendo qui: lanciare un intero su un tipo specifico. –

+0

@mattia: prova a fare questo invece del 'static_cast' inline quindi:' std :: size_t i = 1; vc (i); ' –

6

risoluzione dei nomi è fatto prima la risoluzione di sovraccarico.
Non c'è operator() in c quindi il compilatore cerca il operator() nelle sue classi base e ne trova uno in a e un altro in b rendendo il nome ambiguo (e nessuna risoluzione di sovraccarico ha luogo).

Se si vuole eliminare il nome di ambiguità è possibile chiamare a::operator() esplicitamente: vc.a::operator()(1);

Problemi correlati