必须声明“全局友元运算符重载”来进行序列化总是让我觉得很笨拙。必须在类之外声明序列化运算符似乎不是基础。所以我一直在寻找一个可靠的答案来解释为什么。
(注意:如果有人有更好的 Google-Fu 来找到已经写好的好的答案,我很想读一读。)
我怀疑它在技术上是可行的,并且只是一个符号问题。<<
如果该库被设计为执行and的成员重载>>
,则您必须从右到左构建一系列流操作,而不是从左到右。所以不要写:
Rational r (1, 2);
cout << "Your rational number is " << r;
您必须将输出行编写为:
r >> ("Your rational number is " >> cout);
需要括号来启动反向链接,因为>>
和<<
关联从左到右。没有它们,它将尝试为r >> "Your rational number is "
before找到匹配项"Your rational number is " >> cout
。如果选择了具有从右到左关联性的运算符,则可以避免这种情况:
r >>= "Your rational number is " >>= cout;
(注意:在库中,像字符串文字这样的非类类型必须通过全局运算符重载来处理。)
但这是限制吗?对于任何希望将序列化分派到类中的 iostream 风格的设计来说,这种逆转几乎是不可避免的?我错过了任何其他问题吗?
更新也许“问题”的更好措辞是说我开始怀疑以下内容:
对于希望序列化自己的非流对象,iostream 库可以假设已设计为插入器和提取器是类成员而不是全局重载......并且不会(显着)影响运行时属性。然而,这只有在 iostream 作者愿意接受它会迫使客户端从右到左形成流操作时才有效。
但是我缺乏直觉,为什么全局重载运算符与成员可以解锁从左到右(而不是从右到左)表达自己的其他解锁能力。问题是后见之明、模板或 C++11 的某些深奥特性是否可以提供替代方案。或者,“C++ 物理”是否对一个方向有内在的偏见,而全局重载在某种程度上是本书中唯一用于覆盖它的编译时技巧。