2010-02-19 3 views
2

Prenons l'exemple suivant:Pourquoi les appels de fonction aux classes de base modélisées ne fonctionnent-ils pas?

template <typename T> 
class A { 
    public: 
     void f() { 
      cout << "A::f()\n"; 
     } 
}; 

template<> 
class A<int> { 
}; 

template<typename T> 
class B: public A<T> { 
    public: 
     void g() { 
      cout << "B::g()\n"; 
      A<T>::f(); 
     } 
}; 

int main() { 
    B<int> b;  // (1) 
    b.g();  // (2) 

    return 0; 
} 

Il est évident que l'appel à A :: f() à l'intérieur B :: g() échouera pour le type de modèle int. Ma question est à quel moment l'appel échoue-t-il? À (1) ou (2)? Je pensais que ce devrait être (1) parce qu'à ce stade, le compilateur crée une nouvelle classe avec le type de template int et le compile. Cette compilation devrait échouer dans f() correct?

+0

Quelle est la sortie de main()? – John

+1

@John: Aucun, car la compilation échouera. –

+0

Oh, d'accord. J'étais confus parce que vous parliez de "à quel moment l'appel échoue" - et commente les points dans le code - comme s'il avait été compilé. – John

Répondre

3

Il échoue en 2). La fonction membre des modèles est instanciée lorsqu'elle est appelée. Plus précisément: Lorsqu'un modèle de classe est instancié, la déclaration de ses fonctions membres est instanciée, mais pas leur définition. La définition est instanciée lorsque la fonction est utilisée.

+0

Un fait intéressant est que si vous supprimez la fonction 'f' de toutes les définitions de templates ou de spécialisations explicites de' A' dans cette UT, alors le compilateur est autorisé à marquer la définition de la fonction membre 'g' mal formée et à émettre un diagnostic même si 'B' n'est jamais utilisé, car aucune spécialisation valide ne pourrait jamais être générée pour cette fonction membre (' 14.7/8'). –

4

Il échouera à (2), ce qui est garanti par la norme. Dans la section 14.7.1/1, il est dit que l'instanciation d'une classe de template ne fait pas et non instancier ses définitions de membres. Cela n'arrivera que lorsque le membre sera utilisé.

Si vous supprimez (2) du code, il sera compilé.

14.7.1/1 extrait:
L'instanciation implicite d'une spécialisation de modèle de classe provoque instanciation l' implicite des déclarations, mais pas des définitions ou des arguments par défaut, des fonctions membres de la classe, les classes membres , membres de données statiques et modèles de membre; et il provoque l'instanciation implicite des définitions des unions anonymes membres.

Emphasis mine.


Le diagnostic de Visual Studio est trompeur. Il dira see reference to class template instantiation 'B<T>' being compiled. Qu'est-ce que cela signifie n'est pas "je échoue à l'instanciation de B<T>", mais "je échoue à instancier un membre de la classe B<T>"

+1

La meilleure chose est que VC pointe seulement vers la ligne qui instancie 'B'. Quoi qu'il en soit, j'aurais dû apprendre maintenant à douter de VC et simplement le regarder en premier. –

Questions connexes