2011-01-28 15 views
8

skompilować ten kod z GCC (4.2.1 Jabłko budować 5664)Niejasna definicja operatora() z wielokrotne dziedziczenie

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

i dać mi następujący błąd:

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” • zrozumieć powód, dlaczego ten kod jest niejednoznaczny; dwie metody mają różne podpisy.

+0

Dziwię się, że Clang można skompilować kod, podczas gdy GCC narzeka. – peoro

Odpowiedz

6

Zmienić c w ten sposób:

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

C++ (przed C++ 0x) jest trochę niewygodne w dziedziczeniu funkcje: jeśli podasz funkcję o tej samej nazwie z funkcji klasy bazowej ukrywa te klasy bazowe.

Wygląda na to, że dziedziczenie z dwóch klas ma ten sam problem.

// szukanie standardu ...

+0

Jest tak tylko w przypadku, gdy mają ten sam podpis, którego te funkcje nie mają. –

+0

@Zac Howland: nie jestem pewien, możesz mieć rację, ale GCC nie skompiluje go w inny sposób. Może błąd GCC? Clang skompiluje się bez żadnego problemu z kodem OP ... – peoro

+5

@Zac Howland: ukrywanie się dzieje w przypadku dopasowania nazwy, a nie podpisu. –

1

Jest niejednoznaczny, ponieważ podajesz stałą całkowitą, która może (prawdopodobnie) zostać wyrzucona do typów std::size_t lub index. Zmień main z następującym i powinien go rozwiązać:

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

    return 0; 
} 

Z powiedział, że jest bardzo prawdopodobne, że nie należy używać wielokrotne dziedziczenie tutaj.

+1

Liczba całkowita nie może być rzutowana na typ indeksu. A jeśli spróbujesz skompilować, to nie działa. –

+0

@mattia: Będziesz musiał dokładniej opisać problem. Z tym, co pokazałeś, powyższy kod zadziała (oczywiście, musisz zmienić rzut, jeśli chcesz innego operatora). @peoro: 'static_cast' robi dokładnie to, co tutaj robi - rzutowanie liczby całkowitej na określony typ. –

+0

@mattia: Spróbuj tego zamiast wbudowanego 'static_cast', a następnie:' std :: size_t i = 1; vc (i); ' –

6

Rozpoznawanie nazw odbywa się przed rozładowaniem.
Nie ma operator() w c więc kompilator idzie szuka operator() w jego klas bazowych i odnajduje jeden w a a drugi w b dokonywania nazwa niejednoznaczne (a nie rozdzielczość przeciążenie odbywa).

Jeśli chcesz wyeliminować nazwę niejasności można nazwać a::operator() wyraźnie: vc.a::operator()(1);

Powiązane problemy