Come alcuni dei miei codice richiesto conversione implicita tra matrici di tipo diverso (ad esempio Matrix<int>
a Matrix<double>
), che definisce un costruttore di copia template Matrix<T>::Matrix(Matrix<U> const&)
invece dello standard Matrix<T>::Matrix(Matrix<T> const&)
:Templated costruttore di copia non riesce con specifico tipo template
template <typename T> class Matrix {
public:
// ...
template <typename U> Matrix(Matrix<U> const&);
// ...
private
unsigned int m_rows, m_cols;
T *m_data;
// ...
};
Con un typecast appropriato aggiunto al copy-constructor, questo metodo viene convertito in modo perfetto tra matrici di tipi diversi. Sorprendentemente, fallisce con un errore malloc proprio nella situazione in cui funzionerebbe un semplice costruttore di copie: dove U == T
. Abbastanza sicuro, sovraccaricare il costruttore di copie con la firma predefinita Matrix<T>::Matrix(Matrix<T> const&)
risolve il problema.
Questa è una soluzione scadente, in quanto risulta nella duplicazione all'ingrosso del codice copy-constructor (Letteralmente un copia-incolla invariato). Ancora più importante, non capisco perché c'è un errore malloc
doppio senza il codice duplicato. Inoltre, perché la sintassi estremamente verbosa template <typename T> template <typename U>
qui richiesta rispetto allo standard e molto più succinta, template <typename T, typename U>
?
Sorgente completa del metodo basato su modello, compilata utilizzando G ++ v4.0.1 su Mac OS 10.5.
template <typename T> template <typename U> Matrix<T>::Matrix(Matrix<U> const& obj) {
m_rows = obj.GetNumRows();
m_cols = obj.GetNumCols();
m_data = new T[m_rows * m_cols];
for (unsigned int r = 0; r < m_rows; ++r) {
for (unsigned int c = 0; c < m_cols; ++c) {
m_data[m_rows * r + c] = static_cast<T>(obj(r, c));
}
}
}
La tua spiegazione per l'errore malloc suona perfettamente. C'è una ragione specifica per cui i compilatori non possono utilizzare una funzione membro modello come copia-costruttore? Grazie per l'informazione e il consiglio per evitare la duplicazione del codice. –
Se si dispone di quel modello, non è ancora una funzione. Solo l'utilizzo di esso con alcuni argomenti del template genera una funzione (membro-) al di fuori di essa (chiamata specializzazione). Questo è anche il motivo per cui i template dei membri non possono essere virtuali: non si sa in anticipo quali funzioni sono generate da esso. –
Questo ha molto senso - questo non funziona proprio perché è necessario inoltrare i parametri del modello o includere l'intera fonte dell'implementazione. Grazie ancora. –