2012-09-24 12 views
5

Dato il seguente codice:Moving Template Method a Breaks derivati ​​Compilation

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

Questo compila e funziona bene; le versioni corrette in sovraccarico di B::foo() vengono scelte e chiamate per a e a.t.

Ora mi introdurre una nuova classe che deriva da CB e spostare la versione del modello di ::foo() fuori B e in 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 
} 

E ora il codice non viene compilato più. Visual Studio 2005 è affermando:

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

Infatti, chiamando C::foo() con qualsiasi int risultati di valore in questo errore. Sembra quasi che il sovraccarico del metodo per int venga nascosto dall'overload del modello.

Perché sta succedendo? È un problema con il compilatore di Visual Studio 2005? Sfortunatamente, non posso testarlo su nessun altro compilatore in questo momento.

Qualsiasi informazione è apprezzata.

risposta

5

Sembra quasi che l'overload del metodo per int viene nascosto da sovraccarico modello.

Esattamente! È necessario aggiungere una dichiarazione secondo in classe C:

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

Quando si dichiara una funzione membro in una classe derivata, tutte le funzioni membro della classe base con lo stesso nome sono nascosti. Vedi §3.3.10/3 di ISO/IEC 14882: 2011:

La dichiarazione di un membro in una classe derivata (Clausola 10) nasconde la dichiarazione di un membro di una classe base con lo stesso nome; vedi 10.2.

2

Si nasconde, senza sovraccaricare. Utilizzare

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

Corretto, la funzione di base è nascosta. Questo è in realtà il termine appropriato per questo. Aggiungi using B::foo; alla definizione di classe di C per visualizzarlo.