2010-08-17 5 views
8

J'ai fait le programme suivantQuand avons-nous besoin d'une .template construire

#include <iostream> 
#include <typeinfo> 
template<class T> 
struct Class 
{ 
    template<class U> 
    void display(){ 

     std::cout<<typeid(U).name()<<std::endl; 
     return ; 
    } 

}; 


template<class T,class U> 
void func(Class<T>k) 
{ 
    k.display<U>(); 

} 

int main() 
{ 
    Class<int> d; 
    func<int,double>(d); 
} 

Le programme ci-dessus doesn compile pas parce display() est une fonction de membre de modèle afin d'une qualification de .template avant display() doit être fait. Ai-je raison?

Mais quand je fait le programme suivant

#include <iostream> 
#include <typeinfo> 

template<typename T> 
class myClass 
{ 
    T dummy; 
    /*******/ 
public: 
    template<typename U> 
    void func(myClass<U> obj); 

}; 

template<typename T> 
template<typename U> 

void myClass<T>::func(myClass<U> obj) 
{ 
    std::cout<<typeid(obj).name()<<std::endl; 
} 
template<class T,class U> 
void func2(myClass<T>k) 
{ 
    k.template func<U>(k); //even it does not compile 

} 
int main() 
{ 
    myClass<char> d; 
    func2<char,int>(d); 
    std::cin.get(); 
} 

Pourquoi k.func<char>(k); ne compile pas même après avoir donné une .template construction?

+0

Une réponse complète et complète à cette question peut être trouvée dans l'entrée FAQ de Comeau C++ FAQ, ["Qu'est-ce que la syntaxe' -> template', '.template' et' :: template'? "] (http://www.comeaucomputing.com/techtalk/templates/#templateprefix). –

+1

Je suis bloqué ... §5.2.5/1 dit "Une expression postfixée suivie d'un point ou d'une flèche ->, ** suivi éventuellement du mot-clé template (14.8.1) **, suivi d'un identifiant expression, est une expression postfixée. " Mais 14.8.1 semble être sans rapport, en plus de décrire comment C++ est capable de résoudre les modèles de fonctions membres * sans * le mot-clé. Où ce mot clé est-il spécifié? – Potatoswatter

+0

@Potatoswatter: Le mot-clé est spécifié au §2.11 Tableau 3, bien sûr. ;-) (Sur une note plus sérieuse, c'est une bonne question). –

Répondre

14

Le symbole < signifie à la fois « moins » et "commence les arguments du modèle". Pour distinguer ces deux significations, l'analyseur doit savoir si l'identificateur précédent nomme un modèle ou non.

Par exemple, considérons le code

template< class T > 
void f(T &x) { 
    x->variable < T::constant <3>; 
} 

Soit T::variable ou T::constant doit être un modèle. La fonction signifie différentes choses selon ce qui est et qui n'est pas:

  1. soit T::constant par rapport à 3 obtient et le résultat booléen devient un argument de modèle pour T::variable<>
  2. ou T::constant<3> obtient par rapport à x->variable.

Le désambiguïser, le mot-clé template est nécessaire avant que soit variable ou constant. Cas 1:

template< class T > 
void f(T &x) { 
    x->template variable < T::constant <3>; 
} 

Cas n ° 2:

template< class T > 
void f(T &x) { 
    x->variable < T::template constant <3>; 
} 

Ce serait plutôt bien si le mot-clé était nécessaire que dans des situations réelles ambiguës (qui sont un peu rares), mais il rend l'analyseur beaucoup plus facile à écrire et empêche que de tels problèmes ne vous attrapent par surprise.

Pour standardese, voir 14.2/4:

Lorsque le nom d'un modèle membre spécialisation apparaît après. ou -> dans un postfix-expression, ou après imbriqué-name-spécificateur dans un -id qualifié, et le postfix-expression ou id qualifié dépend explicitement sur un modèle paramètres (14.6.2), le nom du modèle de membre doit être précédé du préfixe par le modèle de mot clé. Sinon, le nom est supposé nommer un non-modèle .

+0

+1 pour le premier exemple: c'est un extrait de code vraiment génial pour démontrer la sensibilité au contexte de la grammaire C++ et pourquoi ces mots-clés sont nécessaires. –

0

Le premier exemple compile et fonctionne très bien pour moi dans VS 2010.

7

L'article 5.1 de C++ Templates explique cette construction en détail

La fonction ci-dessous a un problème

template<class T,class U> 
void func2(myClass<T> k) 
{ 
    k.template func<U>(k); //even it does not compile 

} 

ici T = char et U = int

myclass<char>::func<int>(myclass<char>) 

est bei ng appelé. Cependant, une telle fonction n'existe pas

Même si, dans des circonstances normales de char 'est convertible « int », cela ne vaut pas pour les arguments de modèle explicitement spécifiés

Questions connexes