为什么临时stringstream可绑定到istream&却无法绑定到stringstream&?
问题解答
这一现象的核心原因是C++11起标准库为输入流新增了右值引用版本的operator>>重载,专门适配右值临时流的输入场景:
两种情况的具体差异
1. 自定义operator>>接受std::istream&时可编译的原因
标准库<istream>头文件中提供了如下模板重载:
template <class _Istream, class _Tp> typename std::enable_if<..., _Istream&&>::type operator>>(_Istream&& __is, _Tp&& __x) { __is >> std::forward<_Tp>(__x); return std::move(__is); }
- 这个重载的第一个参数是万能引用,能直接绑定
std::stringstream{}产生的右值临时对象,会优先被匹配。 - 模板内部会把右值流当作左值处理,调用对应的输入运算符。由于
std::stringstream是std::istream的派生类,左值std::stringstream可以直接绑定到std::istream&类型的参数,所以你自定义的operator>>可以被正常调用,编译通过。
2. 自定义operator>>接受std::stringstream&时编译失败的原因
- 此时标准库的右值流重载在实例化时,内部的
__is >> std::forward<_Tp>(__x)调用需要把std::istream&向下转型为std::stringstream&,这个转换不合法,因此触发SFINAE机制,该模板重载被排除出候选集。 - 剩下的唯一候选就是你自定义的
operator>>(std::stringstream&, Foo),但非const左值引用无法绑定到右值临时对象,因此直接报你看到的绑定错误。
你补充日志里的no type named 'type' in 'struct std::enable_if<false, ...>'错误就是标准库重载被SFINAE排除的正常表现。
内容的提问来源于stack exchange,提问作者yeputons
相关产品推荐
相关产品推荐

