§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
}
Live example on Ideone(未定义行为的完美示例。在MSVC10上没有为我打印)。
上面的示例可能看起来很人为,但是在通用代码中或者将(std::stringstream() << "text")
传递给提供左值和右值超载并存储{的函数时,不应该太难以进入这种情况。 {1}}或std::ostream
根据过载以不同的方式。
现在,再次返回std::istream
并指定以下内容的参数是什么?
返回: move(os)
(basic_ostream<charT, traits>&&
也一样。)
有什么我可以忽略的吗?在目前的状态,在我看来,它看起来很危险,就像一个缺陷。我浏览了LWG issue list并找到了this proposal(hi @HowardHinnant!)。它确实返回了一个rvalue,但这只是为了能够链接这个特殊的运算符,而不是专门解决我上面描述的安全问题(虽然肯定 解决它)。此外,它被标记为关闭并重新考虑下一个标准。因此,我想我会在这里问:
为什么上面提到的重载返回左值引用有充分的理由吗?
答案 0 :(得分:15)
这是一个缺陷,这是我的错,抱歉。 LWG 1203(感谢为我找到!:-))是我目前对&#34; rvalue-stream-inserter&#34;的正确解决方案的看法。请注意,你仍然可以抓住它并遇到麻烦:
auto&& s = (std::stringstream() << "hi there!\n");
std::cout << s.rdbuf(); // oops
虽然至少在上面的代码中,你可以做一些你不应该做的事情(因为&&
)更为明显。