Обоснование принуждения некоторых операторов к участию
В C++ есть 4 оператора, которые могут быть перегружены, но не могут быть перегружены как отдельно стоящие (иначе говоря, автономные) функции. Эти операторы:
operator =
operator ()
operator ->
operator []
Эта тема прекрасно объясняет причину запрета operator =
быть функцией без членов. Есть идеи по поводу трех других?
2 ответа
Четыре оператора, упомянутые в оригинальной публикации, =
, ()
, ->
а также []
, действительно должны быть реализованы как нестатические функции-члены (соответственно C++98 §13.5.3/1, §13.5.4/1, §13.5.5/1 и §13.5.6/1).
Как я помню из более ранних дебатов по этому вопросу, обоснование Бьярна Страуструпа заключалось в том, чтобы сохранить некоторое здравомыслие в языке, то есть иметь по крайней мере некоторые вещи, на которые вы могли бы положиться, независимо от того, насколько "кто-то еще" облажался, определяя не являющиеся членами операторы для существующих классы.
Я не уверен, что полностью согласен с тем, что ограничение действительно помогает в этом, но.
РЕДАКТИРОВАТЬ: Я консультировался с Бьярном Страуструпом по этому поводу (он всегда полезен), но кажется, что очевидные несоответствия правил - не более, чем случай замороженной исторической катастрофы. Он отмечает, что "теперь это выглядит хуже, чем было тогда, потому что наши правила для lvalues и ссылок изменились с тех пор, как были сформулированы правила перегрузки. Я пытался разобраться в этой проблеме еще пару лет назад, но у меня не хватило времени, прежде чем произвести полное предложение. "
Ура & hth.,
PS: книга "Дизайн и эволюция C++" отлично подходит для такого рода вопросов, но, к сожалению, у меня ее нет.
В этой теме на comp.std.C++ обсуждается вопрос.
Фрэнсис Глассбороу, который был в комитете, заявил:
Разработчики языка не хотели поддерживать преобразования и продвижения в левом операнде оператора =, а также в операнде () и [].
Стараясь избежать ситуации, когда:
class A {};
class B { B(A& a) {} };
int operator()(B const& b) { return 0; }
int main(void)
{
A a;
// This works even though A doesn't have a () operator
// It creates a temporary B and calls operator()(B& b)
return a();
}