Подтвердить что ты не робот

Почему в С++ не существует ссылки на член?

В С++ я могу выбирать между указателями функций и ссылками на функции (или даже значениями функций для полноты):

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

Однако, когда дело доходит до методов, у меня нет выбора между указателями и ссылками.

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

Это приводит меня к предположению, что ссылки на методы не существуют в С++. Это правда? Если это так, то почему они не существуют?

4b9b3361

Ответ 1

В стандарте (например, N3337 - не последнее, но прекрасно для этого) есть примечание в конце раздела 8.3. 3.3, который гласит:

[Примечание: см. также 5.3 и 5.5. Тип "указатель на член" отличается от типа "указатель", то есть указатель на член объявляется только указателем на синтаксис объявления участника и никогда не указателем синтаксис декларатора. В С++ нет типа "ссылки на член". - end note]

Кроме того, конечно, нет операторов "ссылки на члены" (что, предположительно, лучшее, что я могу придумать, было бы чем-то вроде ->& и .&, хотя они не согласуются с разыменованием ссылки на данные и функции, которые не требуют специального оператора).

Почему?

Что касается причины; после веселого исторического исследования и не найдя на нем каких-либо существующих заметок (я вернулся полностью к Cfront 2.0, где указатель-к-члену был впервые поддержан - изменить: согласно гораздо более достоверный документ, эта функция была сначала поддержана в Cfront 1.2), я сам спросил у человека и вот ответ:

Date: Sat, 22 Feb 2014 10:12:51 -0500
From: Bjarne Stroustrup <...>
Subject: Re: On lack of reference-to-member and CFront 2.0

On 2/22/2014 6:40 AM, Jason C wrote:
> My question is: C++ very clearly disallows the concept of 
> "reference-to-member". Why is this? I have been doing a lot of 
> research, and I traced the origin of "pointer-to-member" back (I 
> think) to 1989 CFront 2.0. I read through the product reference manual 
> and other documentation hoping to find an explanation of some sort but 
> could not.

I don't really remember. It was 25+ years ago and the ARM is silent on 
this. I added pointers to members to eliminate the need for a rare 
breakage of the type system. I suspect that I didn't add references to 
members because it did not seem worth the effort: there was no use case.

Честно говоря, я ожидал чего-то гораздо более загадочного и сложного.

Итак, у вас есть это: в следующий раз, когда кто-нибудь спросит, почему нет ссылки на члена, вы можете с уверенностью сказать: "Потому что нет!" (Примечание: см. Мои оценки в комментариях, еще предстоит провести некоторое историческое исследование, чтобы получить 100% -ную уверенность.)

Лично я ни разу не нашел использования для указателей на членов в моем собственном коде, но явное обоснование их существования дано в Stroustrup Эволюция С++: 1985-1989 гг., Стр. 222-223.


Кстати, ваш синтаксис для вызова гипотетической ссылки на функцию-член:

object.method();

... не имеет большого смысла, поскольку нет возможности отличить это синтаксически от вызова фактическому члену с именем method().

hvd поднимает хороший момент ниже: Как вы можете видеть из вышеизложенного, синтаксически не было бы действительно последовательного способа разыменования ссылки на член. Вы должны отличить его от обычного доступа к члену, но в то же время вы хотите сделать его совместимым с разыменованием ссылок на объекты и функции (которые не требуют специального оператора), и я не могу думать о чем-либо, что выполняет оба.