J'ai pris le projet sur lequel je travaille et l'ai raccourci à trois brefs fichiers qui reproduisent ce qui se passe. Je travaille avec l'IDE Code :: Blocks en utilisant g ++ sous la norme 2011. Les fichiers sont main.cpp
, thing.cpp
et thing.h
. L'en-tête (.h
) a des déclarations et la source (.cpp
) a des implémentations. Les fichiers thing
définissent une classe Thing
avec un paramètre de modèle T
. Tous Thing
est détenir un objet de type T
(il ne fait essentiellement rien).Pourquoi l'inclusion d'une en-tête entraîne-t-elle une erreur «utilisation de l'auto avant déduction de l'auto»?
main.cpp
:
#include <iostream>
#include "thing.h"
int main(){
Thing<int> a(9);
Thing<double> b(3.2);
auto c = a + b;
c.display();
return 0;
}
thing.h
:
#ifndef THING_H
#define THING_H
template<typename T>
class Thing{
private:
T content;
public:
Thing(const T& content);
~Thing(){};
T get_content() const;
void display();
};
template<typename S, typename T>
auto operator+(const Thing<S>& s, const Thing<T>& t);
#endif // THING_H
thing.cpp
:
#include "thing.h"
#include <iostream>
template<typename T>
Thing<T>::Thing(const T& content)
:content(content){}
template<typename T>
void Thing<T>::display(){
std::cout << content << '\n';
}
template<typename T>
T Thing<T>::get_content() const {
return content;
}
template<typename S, typename T>
auto operator+(const Thing<S>& s, const Thing<T>& t){
S s_content = s.get_content();
T t_content = t.get_content();
Thing<typename std::common_type<S, T>::type> sum = s_content + t_content;
return sum;
}
Voici le comportement étrange: le code compilera ou non en fonction de la ligne #include "thing.h"
. L'utilisation thing.h
ici ne compilera pas, ce qui provoque une erreur:
error: use of 'auto operator+(const Thing<S>&, const Thing<T>&) [with S = int; T = double]' before deduction of 'auto'
error: invalid use of 'auto'
La modification de cette ligne #include "thing.cpp"
permet au code de compiler sans problèmes et qu'il fonctionne comme prévu (il sort 12.2
à la console).
Ma question est: Qu'est-ce que le compilateur fait différemment dans les deux cas? Comment est-ce que je peux changer le code pour éliminer cette erreur quand includ
ing l'en-tête?
Merci d'avance.
Vous devriez probablement vous demander [pourquoi vous n'êtes pas mise en œuvre de vos modèles dans un en-tête] (https: // stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) en premier lieu? Il est impossible pour un appelant de déduire le 'auto' donné uniquement' 'auto-opérateur + (const Thing
& s, const Thing & t);' pour travailler avec le code –
WhozCraig
@WhozCraig Pourquoi l'appelant n'a-t-il accès qu'à l'en-tête et non l'implémentation dans le fichier source? En fait, comment un appelant accède à la source dans d'autres situations? Mon impression était que lorsque la fonction est appelée, le compilateur remplacera dans l'implémentation, dans lequel le type de retour automatique peut être déduit – Johan
Le compilateur ne peut pas faire cela parce qu'il a besoin de la définition de modèle à portée de main quand vous êtes sur le point de l'utiliser.Main est une unité de traduction, Thing en est une autre, et la définition de la classe modèle de 'Thing' n'existe pas dans l'unité principale. –