web-dev-qa-db-fra.com

Pourquoi la classe d'amis déclarée ne peut-elle pas être renvoyée dans la classe?

Le code suivant ne compile pas:

struct X {
  friend class Y;
  Y* ptr;
};

Cppreference décrit la situation comme suit:

... Si le nom de la classe utilisée dans la déclaration de l'ami est pas encore déclaré, il est déclaré en avant sur place.

Si le "point" signifie l'endroit où la relation d'amitié est déclarée, le membre Y* ptr devrait pouvoir être déclaré. Pourquoi ne compile-t-il pas? Où dans la norme l'interdit?

27
Kan Li

C'est une erreur sur le site. Cela contredit la norme qui dit que la déclaration d'amitié ne remplace pas une déclaration anticipée:

7.3.1.2.3 Chaque nom d'abord déclaré dans un espace de noms est membre de cet espace de noms. Si une déclaration d'amis dans une classe non locale déclare d'abord une classe, une fonction, un modèle de classe ou un modèle de fonction, l'ami est membre de l'espace de noms le plus proche. La déclaration d'ami ne rend pas le nom visible en tant que recherche qualifiée ou non qualifiée.

La partie sur le fait que le nom n'est pas visible par une recherche qualifiée ou non qualifiée signifie essentiellement que le nom ne se comporte pas comme une déclaration avant.

29
dasblinkenlight

En plus de la réponse de @dasblinkenlight, une note dans 3.3.2 Point de déclaration allumé. 10 indique explicitement qu'une déclaration d'amis n'introduit pas (et donc ne "fait pas de déclaration") un nom de classe:

10 [Remarque: les déclarations d'ami font référence à des fonctions ou à des classes qui sont les membres de l'espace de noms englobant le plus proche, mais ils n'introduisent pas nouveaux noms dans cet espace de noms ([namespace.memdef]).

2
Stephan Lechner

Une façon de corriger ce code est de simplement ajouter class mot-clé :

struct X {
    friend class Y;
    class Y* ptr;
};

Ceci transmettra la déclaration class Y à la portée globale, si X est dans la portée globale.

0
Evg