Modèle amie fonction d'une classe template

J'ai été aux prises avec le problème décrit dans cette question (la déclaration d'une fonction de modèle comme un ami d'un modèle de classe), et je crois que la 2ème réponse est ce que je veux faire (avant de déclarer la fonction de modèle, puis le nom d'une spécialisation comme un ami). J'ai une question un peu différente de la solution est correcte ou arrive juste à travailler dans Visual C++ 2008.

Code de Test est:

#include <iostream>

//forward declarations
template <typename T>
class test;

template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t);

template <typename T>
class test {
  friend std::ostream& operator<< <T>(std::ostream &out, const test<T> &t);
  //alternative friend declaration
  //template <typename U>
  //friend std::ostream& operator<<(std::ostream &out, const test<T> &t);

  //rest of class
  };

template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t) {
  //output function defined here
  }

Tout d'abord, une chose étrange que j'ai trouvé était que si je change la déclaration anticipée de operator<< de sorte qu'il ne correspond pas (par exemple, std::ostream& operator<<(std::ostream &out, int fake);, tout compile et fonctionne correctement (pour être clair, je n'ai pas besoin de définir une telle fonction, seul le déclarer). Cependant, comme liés à la question, le retrait de la déclaration anticipée sont les causes d'un problème, car le compilateur semble penser que je suis déclaration d'un membre de données à la place d'un ami de la fonction. Je suis assez sûr que ce comportement est un Visual C++ 2008 bug.

La chose intéressante est que lorsque je retire la déclaration et l'utilisation de la variante de l'ami de la déclaration dans le code ci-dessus. Notez que le paramètre de modèle U n'apparaît pas dans la suite de la signature. De plus, cette méthode compile et fonctionne correctement (sans rien changer d'autre). Ma question est de savoir si cela est conforme à la norme ou à une idiosyncrasie de Visual C++ 2008 (je ne pouvais pas trouver une bonne réponse dans mes livres de référence).

Noter que, si un ami de la déclaration de template <typename U> friend ... const test<U> &t); fonctionne aussi, cela donne effectivement chaque instance de l'opérateur friend accès à toute instance de test, tout ce que je veux, c'est que les membres privés de test<T> ne devrait être accessible à partir de operator<< <T>. J'ai testé ce par l'instanciation d'un test<int> à l'intérieur de la operator<< et l'accès à un membre privé, ce qui devrait provoquer une erreur de compilation lorsque j'essaie de sortie d'un test<double>.

Synopsis: le Retrait de la déclaration et de passer à l'alternative ami de déclaration dans le code ci-dessus semble produire le même résultat (en Visual C++ 2008) -- est-ce code fait-il correct?

Mise à JOUR: Toutes les modifications ci-dessus pour le code ne fonctionne pas sous gcc, donc je suppose que ce sont des erreurs ou des "features" dans le compilateur Visual C++. Encore, je vous en serais reconnaissant idées de personnes familières avec le standard.

D'ailleurs, j'ai compris que l'ajout de using namespace std; avant la déclaration de la classe supprime la nécessité pour la déclaration, qui je suppose est un des effets secondaires de la (possible) de compilateur bug.
Comme pour mon comment - pouvez-vous ajouter explicitement les exemples (y compris l'instanciation) qui vous disent de travail? Verbalement, il est assez difficile de comprendre ce que tu veux dire pour chaque exemple.

OriginalL'auteur Sumudu Fernando | 2009-11-24