Comme certains de mon code nécessaire conversion implicite entre matrices de types différents (par exemple Matrix<int>
à Matrix<double>
), je défini un constructeur de copie basé sur un modèle Matrix<T>::Matrix(Matrix<U> const&)
au lieu du Matrix<T>::Matrix(Matrix<T> const&)
standard:copie constructeur Templated échoue avec le type basé sur un modèle spécifique
template <typename T> class Matrix {
public:
// ...
template <typename U> Matrix(Matrix<U> const&);
// ...
private
unsigned int m_rows, m_cols;
T *m_data;
// ...
};
Avec un doublon approprié ajouté au constructeur de copie, cette méthode a parfaitement converti entre matrices de types différents. Étonnamment, il échoue avec une erreur malloc dans la situation même où un simple constructeur de copie fonctionnerait: où U == T
. Effectivement, surcharger le constructeur de copie avec la signature par défaut Matrix<T>::Matrix(Matrix<T> const&)
résout le problème.
Ceci est une mauvaise solution, car il en résulte la duplication en gros du code du constructeur de copie (littéralement un copier-coller inchangé). Plus important encore, je ne comprends pas pourquoi il y a une erreur sans double malloc
sans le code en double. En outre, pourquoi la syntaxe template <typename T> template <typename U>
extrêmement verbeuse est-elle requise ici plutôt que la norme, et beaucoup plus succincte, template <typename T, typename U>
?
Source complète de la méthode basée sur un modèle, compilée à l'aide de G ++ v4.0.1 sur 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));
}
}
}
Votre explication de l'erreur malloc sonne sur place. Existe-t-il une raison spécifique pour laquelle les compilateurs ne peuvent pas utiliser une fonction de membre de modèle en tant que constructeur de copie? Merci pour les informations et pour les conseils pour éviter la duplication de code. –
Si vous avez ce modèle, ce n'est pas encore une fonction. Seul son utilisation avec un argument de template génère une fonction (membre) hors de lui (appelée une spécialisation). C'est également la raison pour laquelle les modèles de membres ne peuvent pas être virtuels: vous ne savez pas à l'avance quelles sont les fonctions qui en sont générées. –
Cela a beaucoup de sens - cela ne fonctionne pas pour la raison même que l'on doit soit renvoyer les paramètres du modèle de déclaration, soit inclure la source complète de l'implémentation. Merci encore. –