提问人:Fareanor 提问时间:9/19/2022 最后编辑:Peter MortensenFareanor 更新时间:1/26/2023 访问量:2056
为什么编译器现在接受从 std::stringstream::operator<<() 对返回的 std::ostream& 调用 str() 成员?
Why do compilers now accept to call str() member on a returned std::ostream& from std::stringstream::operator<<()?
问:
请考虑以下行:
std::string s = (std::stringstream() << "foo").str();
这不应该编译,因为被继承并返回一个没有成员。std::stringstream::operator<<()
std::ostream
std::ostream&
str()
似乎主要编译器现在正在接受过去没有的代码。发生了什么标准更改来编译它?
我用 GCC、Clang 和 MSVC 做了一些测试,我可以找到发生更改的版本:
编译器 | 拒绝时间(版本) | 接受自(版本) |
---|---|---|
海湾合作委员会 | 11.1 | 11.2 |
铛 | 12.0.1 | 13.0.0 |
MSVC公司 | 19.14 版 | 19.15 版 |
你可以在这里找到测试
答:
45赞
3 revsmolbdnilo
#1
它们几乎同时添加了右值重载(见此处)。
右值重载是在添加到 C++ 11 中引入的,并返回与其左侧操作数相同类型的流。
正如评论中所指出的,它似乎在整整十年后被添加到编译器中的原因是,它是追溯性地添加到 C++11 中的,而且是最近才添加到的,可能是在被批准包含在 C++20 之后。
我正在把它变成一个社区维基,以防有人有意愿和耐心去寻找追溯添加背后的原因并修改答案。
评论
1赞
Hans Olsson
9/20/2022
我阅读规范的方式是在 2018-05-25 之后在 C++ 11 中追溯引入的;这意味着他们都迟到了,添加了一个添加得很晚的功能。
0赞
molbdnilo
9/21/2022
@HansOlsson 这听起来很有道理。你介意我把它添加到答案中吗?
1赞
Karl Nicoll
9/21/2022
@hansolsson - 当你说在 C++11 中引入时,你的意思是在 C++20 中引入还是在 2018 年被添加到(被取代 3 次)C++11 规范中?
0赞
quetzalcoatl
9/21/2022
@KarlNicoll:Hans 强调“追溯性”,所以我把它理解为“是的,回到了过去,并添加到了旧规范中”。奇怪的事情,但有时会发生在非常重要的功能上。不过我不是汉斯,所以不是100%确定。
1赞
Karl Nicoll
9/21/2022
@quetzalcoatl - 是的,我想你是对的,它在 cppref 中被列为 c++11 功能。这样的功能被向后移植到这么久以前,但又需要很多年才能获得广泛的编译器支持,这似乎很疯狂。这似乎不值得付出努力!疯狂的东西。
评论
auto t = (std::stringstream() << "foo"); std::cout << typeid(t).name() << "\n";
t
.str()
(std::stringstream() << "foo")