2008-12-24 7 views
17

Est-ce que quelqu'un sait pourquoi les typedefs de noms de classes ne fonctionnent pas comme les noms de classe pour la déclaration d'ami?Pourquoi ne puis-je pas déclarer un ami via un typedef?

class A 
{ 
public: 
}; 

class B : public A 
{ 
public: 
    typedef A SUPERCLASS; 
}; 

typedef A X; 

class C 
{ 
public: 
    friend class A;    // OK 
    friend class X;    // fails 
    friend class B::SUPERCLASS; // fails 
}; 

Répondre

9

Il ne peut pas, actuellement. Je ne connais pas encore la raison (juste en regardant ça, parce que je trouve cela intéressant). Mise à jour: vous pouvez trouver la raison dans la première proposition pour soutenir les noms de typedef comme amis: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1520.pdf. La raison en est que la norme ne prend en charge que les spécificateurs de type élaborés. Il est facile de n'autoriser que ceux-là, et de dire que si l'entité déclarée comme ami n'est pas encore déclarée, elle deviendra un membre de l'espace de noms environnant. Mais cela signifie que si vous souhaitez utiliser un paramètre de modèle, vous devez faire (une classe est nécessaire, par exemple)

friend class T; 

Mais cela entraîné des problèmes supplémentaires, et il a été pensé ne vaut pas le gain. Maintenant, l'article propose de donner des spécificateurs de type supplémentaires (de sorte que cela permette ensuite l'utilisation de paramètres de modèles et de noms de typedef).

La prochaine version C++ (due à 2010) sera en mesure de le faire.

Voir cette proposition mise à jour de la norme: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf. Il n'autorise pas uniquement les noms de typedef, mais aussi les paramètres de modèle à utiliser comme type déclaré comme ami.

0

AFAIK, en C++ typedef ne crée pas un synonymes à part entière lorsqu'ils sont utilisés conjointement avec les classes. En d'autres termes, ce n'est pas comme une macro. Parmi les restrictions figure le fait que le synonyme ne peut pas apparaître après un préfixe de classe ou de structure, ou être utilisé comme destructeur ou comme nom de constructeur. Vous ne pouvez pas non plus sous-classer le synonyme. Je parierais que cela signifie aussi que vous ne pouvez pas l'aimer.

1

J'ai essayé dans le VC 8.0 le code:

... 
class C 
{ 
public: 
    friend class A;  
    friend X;    
    friend B::SUPERCLASS; 
}; 
... 

Il est compilé sans erreurs.

Je ne suis pas au courant s'il s'agit de MS spécifique ou non.

0

Un typedef définit un type. Les codes amis déclarent des classes ou des fonctions d'amis (essentiellement des étendues), qui ont alors un "accès" à la zone non publique de la classe déclarante ...

Primitives, par exemple. un float ou un int * ne définissent pas une portée avec un code etc., ils n'utilisent pas la classe de toute façon. N'oubliez pas, vous pouvez également "empaqueter" les conventions d'appel, les attribs d'alignement et d'autres éléments spécifiques au compilateur dans un typedef, c'est-à-dire plusieurs TYPES vectoriels implémentés par la même classe mais avec des attributs d'alignement distincts. => Un type n'est pas une classe, mais vice versa. À mon humble avis, déclarer un ami typedef peut être utile, mais quand "class typedefs" de n'importe où peut être défini comme ami, les amitiés peuvent devenir extrêmement incompréhensible et donc sujettes aux erreurs, en particulier lorsque les modèles sont utilisés excessivement.

L'invalidation d'un seul fichier typedef peut perturber l'ensemble du projet en raison de dépendances étendues. Les amis modèles et les typedefs du modèle 0x sont utiles, mais ne relâchez pas les règles d'une déclaration d'ami.

Je ne connais pas de proposition concernant les typedefs d'amis.

0
class MyClass 
{ 
    friend class ClassFromTypedef; 

    // ... 
}; 

ne fonctionne pas pendant

template<class T> 
struct get_type{ typedef T type;}; 

class MyClass 
{ 
    friend class get_type<ClassFromTypedef>::type; 

    // ... 
}; 

semble fonctionner pour moi gcc-4.6.0 avec l'option --std = C++ 0x (je ne sais pas si elle est important). ne fonctionne pas ... (Désolé, j'étais hallucinant)

+2

Puisque votre réponse ne fournit aucune information utile, avez-vous pensé à la supprimer? –

Questions connexes