6

Considérez ce code:ADL et injection ami

template <int N> 
struct X 
{ 
friend void f(X *) {} 
}; 

int main() 
{ 
f((X<0> *)0); // Error? 
} 

compilateurs semblent être en désaccord fortement. (MSVC08/10 dit non, GCC < 4,5 dit oui, mais 4,5 dit non, soleil 5.1 dit oui, Intel 11.1 dit oui aussi mais comeau dit non (les deux sont EDG)).

Selon « C++ Modèles - Le guide complet »:

... on suppose qu'un appel impliquant une recherche des amis dans classes associées provoque en fait la classe à instancier .. Bien que était clairement destiné par ceux qui ont écrit le standard C++, ce n'est pas clairement énoncé dans la norme.

Je n'ai pas trouvé la section pertinente dans la norme. Toute référence?

Tenir compte de cette variation:

template <int N> 
struct X 
{ 
template <int M> 
friend void f(X<M> *) {} 
}; 

template <> 
struct X<0> 
{ 
}; 

int main() 
{ 
X<1>(); 
f((X<0> *)0); // Error? 
} 

La question clé ici est wether la fonction viable injectée par X<1> doit être visible pendant ADL pour X<0>? Sont-ils associés? Tous les compilateurs mentionnés ci-dessus acceptent ce code, à l'exception de Comeau qui ne l'accepte qu'en mode relâché. Je ne suis pas sûr de ce que la norme a à dire à ce sujet non plus.

Que pensez-vous de cela?

Répondre

4

La norme dit à 14.7.1/4

Une spécialisation de modèle de classe est implicitement instanciée si le type de classe est utilisée dans un contexte qui exige un type d'objet complètement défini ou si l'intégralité du type de classe affecte la sémantique du programme; en particulier, si une expression dont le type est une spécialisation de modèle de classe est impliquée dans la résolution de surcharge, la conversion de pointeur, la conversion de pointeur en membre, la spécialisation de modèle de classe est implicitement instanciée (3.2);

Notez que Vandervoorde fait une issue report here, et le comité a

La norme spécifie déjà que cela crée un point de instanciation.

Pour votre deuxième cas, vous devez prendre en compte les classes et les espaces de noms associés de l'argument f(X<0>*). Ce sont, puisqu'il s'agit d'un pointeur vers une spécialisation de template de classe (notez que "template-id" ci-dessous n'est pas tout à fait correct - C++ 0x corrigé pour utiliser le bon terme) et aussi un pointeur vers une classe a également été corrigé en C++ 0x - il liste ces deux cas dans un point de balle).

  • Si T est un modèle-id, ses espaces de noms et classes associées sont l'espace de noms dans lequel est défini le modèle; [... beaucoup de bruit ...]

  • Si T est un type de classe (y compris les unions), ses classes associées sont: la classe elle-même; la classe dont il est membre, le cas échéant; et ses classes de base directes et indirectes. Ses espaces de noms associés sont les espaces de noms dans lesquels ses classes associées sont définies.

Donc, pour résumer, nous avons en tant que classes associées sont X<0> et les espaces de noms associés sont l'espace de noms global. Maintenant, les fonctions amies qui sont visibles sont

  • Un ami namespace-champ d'application les fonctions déclarées dans les classes associées sont visibles dans leurs espaces de noms respectifs, même si elles ne sont pas visibles lors d'une recherche ordinaire

Il n'y a aucune fonction d'ami déclarée dans X<0> ainsi la déclaration de fonction d'ami n'est pas visible en regardant dans l'espace de noms global. Notez que X<0> est un type de classe entièrement différent de X<1>. L'instanciation implicite de X<1> que vous faites là n'a aucun effet sur cet appel - il ajoute juste un nom non-visible dans l'espace de noms global qui se rapporte à une fonction d'ami de la classe X<1>.

+0

Le premier exemple devrait-il être compilable? – jpalecek

+0

Merci :) C'est plus ou moins ce que je soupçonnais. Comment se fait-il que tant de compilateurs se trompent dans ce deuxième cas? En outre, je l'apprécierais si vous pouviez donner des références dans la norme pour les autres citations aussi. – uj2

+0

@ uj2 Eh bien, au moins clang continue de paraître bien en comparaison de GCC. Il rejette correctement le deuxième cas. En particulier, GCC a un certain nombre de problèmes de conformité de modèles, ce qui ne me surprend pas. Quelles sont les autres citations que vous essayez de trouver des paragraphes standard pour? –