Pourquoi la référence à un membre n’existe-t-elle pas en C ++?

En C ++, je peux choisir entre les pointeurs de fonction et les références de fonction (ou même les valeurs de fonction pour des raisons de complétude):

void call_function_pointer (void (*function)()) { (*function) (); } void call_function_reference (void (&function)()) { function (); } void call_function_value (void function()) { function (); } 

Cependant, en ce qui concerne les méthodes, je ne semble pas avoir le choix entre les pointeurs et les références.

 template  void call_method_pointer (T* object, void (T::*method)()) { (object->*method) (); } // the following code creates a comstack error template  void call_method_reference (T& object, void (T::&method)()) { object.method (); } 

Cela me conduit à supposer que les références aux méthodes n’existent pas en C ++. Est-ce vrai? Si c’est le cas, quelle est la raison pour laquelle ils n’existent pas?

Dans la norme (par exemple, N3337 – pas la dernière, mais très bien pour cela), il y a une note à la fin de la section 8.3.3.3 qui se lit comme suit:

[Remarque: voir aussi 5.3 et 5.5. Le type “pointeur sur membre” est distinct du type “pointeur”, c’est-à-dire qu’un pointeur sur membre est déclaré uniquement par la syntaxe pointeur sur membre déclarateur, et jamais par la syntaxe pointeur déclarateur. Il n’y a pas de type “reference-to-member” en C ++. – note de fin]

De plus, bien sûr, il n’existe pas d’opérateur de type “membre” (ce qui, hypothétiquement, serait le mieux que je puisse trouver serait ->& et .& , Bien que cela ne soit pas compatible avec le déréférencement des références de données et de fonctions , qui ne nécessitent aucun opérateur spécial).

Pourquoi?

Quant à pourquoi; après une petite enquête historique amusante et je n’ai trouvé aucune note existante (j’allais jusqu’à Cfront 2.0 où le pointeur vers membre était supporté pour la première foismodifier: selon un document beaucoup plus crédible , la fonctionnalité était en réalité d’abord pris en charge dans Cfront 1.2 ), j’ai demandé à l’homme lui-même et voici la réponse:

 Date: samedi 22 février 2014 10:12:51 -0500
 De: Bjarne Stroustrup <...>
 Objet: Re: Manque de références aux membres et à CFront 2.0

 Le 22/02/2014 06:40, Jason C a écrit:
 > Ma question est la suivante: C ++ interdit très clairement le concept de 
 > "référence à membre".  Pourquoi est-ce?  J'ai fait beaucoup de 
 > la recherche, et j'ai tracé l'origine du "pointeur-à-membre" en arrière (je 
 > pensez) à 1989 CFront 2.0.  J'ai lu le manuel de référence du produit 
 > et d’autres documents dans l’espoir de trouver une explication, mais 
 > ne pouvait pas.

 Je ne me souviens pas vraiment.  C'était il y a plus de 25 ans et l'ARM est silencieux 
 ce.  J'ai ajouté des pointeurs aux membres pour éliminer le besoin d'un rare 
 rupture du système de types.  Je soupçonne que je n’ai pas ajouté de références à 
 membres car cela ne semblait pas valoir la peine: il n’y avait pas de cas d’utilisation.

Pour être honnête, je m’attendais à quelque chose de beaucoup plus obscur et compliqué.

Vous y êtes donc: la prochaine fois que quelqu’un vous demande pourquoi il n’y a pas de référence à un membre, vous pouvez dire en toute confiance: “Parce qu’il n’y en a pas!” (Remarque: Voir mes commentaires dans les commentaires; il rest encore des recherches historiques à faire pour atteindre un niveau de confiance de 100%.)

Personnellement, je n’ai jamais trouvé d’utilisation pour les pointeurs vers les membres dans mon propre code, mais une explication distincte de leur existence est donnée dans The Evolution of C ++: Stroustrup, 1985-1989 , p. 222-223.


À propos, votre syntaxe pour appeler la fonction hypothétique de référence à membre:

 object.method(); 

… n’a pas beaucoup de sens, car il n’y a aucun moyen de distinguer cela syntaxiquement d’un appel à un membre réel nommé method() .

hvd soulève un bon point ci-dessous: Comme vous pouvez le constater ci-dessus, syntaxiquement, il n’existerait pas de méthode cohérente pour déréférencer une référence à un membre. Vous devez le distinguer de l’access de membre normal, mais vous voulez en même temps le rendre cohérent avec le déréférencement des références d’object et de fonction (qui ne nécessite aucun opérateur spécial), et je ne peux vraiment pas penser à quoi que ce soit qui accomplisse les deux.