2009-11-09 4 views
2

Il est difficile d'avoir un mot pour ça. Parfois, je vois une classe comme celle-ci:Recherche de modèle en classe?

template <typename T> 
class Wrapper 
{ 
public: 
    Wrapper(const T& t) : t_(t) {} 
    Wrapper(const Wrapper& w) : t_(w.t_) {} 
private: 
    T t_; 
} 

Autant que je peux dire c'est un code légitime. Cependant, pourquoi le constructeur de copie est-il autorisé à accepter un const Wrapper& sans indiquer explicitement qu'il a besoin d'un const Wrapper<T>&. Quand d'autre est le type de modèle implicite? Est-il permis d'écrire le constructeur de la copie de cette façon si vous n'utilisez pas une définition en classe?

Répondre

3

Il est explicitement spécifié par la norme linguistique en 14.6.1/1:

Within the scope of class template, when the name of the template is neither qualified nor followed by <, it is equivalent to the name of the template followed by the template-parameters enclosed in <>.

Cela a été reformulée (à travers le concept de « nom de la classe injectée ») dans les versions ultérieures de la norme, mais le fait est que ce comportement est explicitement épelé dans le document.

Pour répondre à la deuxième partie de votre question, cette règle s'applique également aux déclarations de paramètres lors de l'écriture de définitions de méthodes hors classe, mais elle ne s'applique pas aux déclarations de type de retour. Par exemple, ce code est OK

template <typename T> struct S { 
    S foo(S); 
}; 

template <typename T> S<T> S<T>::foo(S s) { 
    /* whatever */ 
} 

mais vous ne pouvez pas retirer le du type de retour bit <T> dans la définition de la méthode. (Et vous ne pouvez pas supprimer <T> du nom qualifié de la méthode.)

Quant au constructior spécifiquement: votre devrait utiliser le nom complet (avec <T>) pour la classe, mais vous ne devriez pas utiliser <T> au nom du constructeur lui-même. Ainsi, la forme la plus courte pour la définition hors classe dans votre cas serait

template <typename T> Wrapper<T>::Wrapper(const Wrapper& w) : t_(w.t_) 
{ 
} 

Notez que vous ne pouvez pas ajouter le bit <T> au nom du constructeur, même si vous voulez

template <typename T> Wrapper<T>::Wrapper<T>(const Wrapper& w) 
             ^ERROR !!! 

PS Cette dernière demande a besoin de plus de recherches. Le compilateur Comeau Online pense que c'est une erreur, alors que GCC pense que c'est OK. Je reviendrai plus tard.

P.P.S. Le compilateur MSVC++ 2005 se plaint de cette dernière déclaration avec un avertissement

warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead 

Intéressant ...

+0

J'ai essayé avec GCC 4.4.2, et il rejette avec « main1.cpp: 4: erreur: utilisation incorrecte du constructeur en tant que modèle ". J'ai envoyé une réponse à votre question Usenet, je pense qu'il devrait apparaître bientôt, avec quelques réflexions sur ce genre de choses. –

3

Fondamentalement, dans une définition de modèle de classe que vous êtes autorisé à utiliser le modèle pour le modèle nom étant défini comme un raccourci pour la version complète paramétrés du modèle id-.

0

Dans une classe basée sur un modèle comme celui-ci, l'utilisation du nom de la classe est identique à l'utilisation de Wrapper<T>.

0

Non, hors de la classe, vous devez écrire:

template <typename T> 
Wrapper<T>::Wrapper<T>(const Wrapper<T>& w) : t(w.t) {} 

Mais à l'intérieur de la classe, Wrapper représente la "classe actuelle".

EDIT: Ceci est pour Andrew et son enquête sur la raison pour laquelle un compilateur rejetterait le sur le constructeur:

template <typename T> 
class Foo { 
public: 
    Foo() {} 
    Foo(const Foo& f); 
}; 

template <typename T> 
Foo<T>::Foo<T>(const Foo<T>& f) { } 

int main(int argc, char** argv) 
{ 
    Foo<int> f; 
    Foo<int> g(f); // make sure the template is instantiated 
} 
+0

Il n'est pas nécessaire d'utiliser 'Wrapper ' dans la déclaration des paramètres. Juste 'Wrapper' est parfaitement suffisant. – AnT

+1

En fait, ce qui précède est incorrect. Il est toujours illégal d'utiliser le '' dans le nom du constructeur lui-même. Il devrait être 'Wrapper :: Wrapper (... '. – AnT

+0

Toujours? Compile juste bien dans MSC6. \ R \ n \ r \ n Je n'ai pas accès à gcc au travail, lamentablement – jmucchiello

Questions connexes