Необходимость объявлять «глобальную перегрузку оператора друга» для сериализации всегда казалась мне неуклюжей. Казалось нецелесообразным объявлять операторы сериализации за пределами вашего класса. Поэтому я искал внятный ответ, почему.
(Примечание: если у кого-то есть лучший Google-Fu, чтобы найти уже написанный хороший ответ, мне было бы интересно это прочитать.)
Я подозреваю, что это технически возможно, и это только вопрос обозначений. Если бы библиотека была разработана для перегрузки членов <<
и >>
, вам пришлось бы строить линию потоковых операций справа налево, а не слева направо. Поэтому вместо того, чтобы писать:
Rational r (1, 2);
cout << "Your rational number is " << r;
Вы должны были бы написать строку вывода как:
r >> ("Your rational number is " >> cout);
Круглые скобки нужны, чтобы начать обратную цепочку, потому что >>
и <<
связаны слева направо. Без них он попытается найти совпадение для r >> "Your rational number is "
до "Your rational number is " >> cout
. Был оператор с ассоциативностью справа налево был выбран, этого можно было бы избежать:
r >>= "Your rational number is " >>= cout;
(Примечание: внутри библиотеки о типах, не относящихся к классу, таких как строковый литерал, придется позаботиться с помощью глобальных перегрузок операторов.)
Но является ли это пределом, и такое обращение практически неизбежно для любого дизайна в стиле iostream, который хотел бы, чтобы сериализация была отправлена в класс? Я пропустил какие-либо другие проблемы?
ОБНОВЛЕНИЕ Возможно, лучше сформулировать «проблему» так: я подозреваю следующее:
Для непотоковых объектов, которые хотят сериализоваться, библиотека iostream гипотетически МОЖЕТ быть спроектирована таким образом, чтобы средства вставки и извлечения были членами класса, а не глобальными перегрузками... и без (значительного) влияния на свойства времени выполнения. Тем не менее, это сработало бы ТОЛЬКО в том случае, если бы авторы iostream были готовы признать, что это заставит клиентов формировать потоковые операции справа налево.
Но мне не хватает интуиции о том, почему глобальная перегрузка оператора по сравнению с членом может разблокировать неразблокируемую в противном случае способность выражать себя слева направо (вместо справа налево). Вопрос в том, могут ли ретроспективные взгляды, шаблоны или какая-то эзотерическая особенность C++11 предложить альтернативу. ИЛИ имеет ли «физика C++» врожденный уклон в сторону одного направления по сравнению с другим, и глобальная перегрузка каким-то образом является единственным трюком во время компиляции в книге для его переопределения.
Сравните с правилом левой руки Флеминга для двигателей