§27.7.3.9
定义了以下重载形式的 operator<<
:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
效果:
os << x
返回:os
(§27.7.2.6
定义了 operator>>
的右值重载函数。)
基本上,它只是转发到左值重载函数。我认为这个重载函数相当危险(事实上,istream
版本比 ostream
版本更加危险),请考虑以下内容:
#include <sstream>
#include <iostream>
int main(){
auto& s = (std::stringstream() << "hi there!\n");
std::cout << s.rdbuf(); // oops
}
Ideone上的实时示例(未定义行为的完美示例。在我的MSVC10上没有输出任何内容)。
上面的示例看起来可能是刻意构造的,但在通用代码或将 (std::stringstream() << "text")
传递给提供 lvalue 和 rvalue 重载的函数且根据重载以不同方式存储 std::ostream
或 std::istream
时,很容易陷入这种情况。
现在,对于返回 basic_ostream<charT, traits>&&
并指定以下内容,是否有反对意见?
返回: move(os)
(对于 basic_istream
同样适用。)
我是否忽略了什么?在当前状态下,在我看来,它看起来危险而且像一个缺陷。我浏览了LWG问题列表并找到了这个建议(嗨@HowardHinnant!)。它确实返回一个 rvalue,但仅为了能够链接该特殊运算符,而不是专门解决我上面描述的安全问题(尽管它肯定解决了这个问题)。此外,它被标记为关闭状态,并重新考虑下一个标准。因此,我想在这里问:
为什么上述重载返回左值引用?有什么好理由吗?