从istream读取自定义类型失败时的预期行为
Expected behaviour when failing reading a custom type from an istream
假设我有一个类有两个数据成员:
class X {
std::string a;
int b;
public:
ostream& print(ostream& os);
istream& read(istream& is);
}
print
函数输出所有格式良好的数据,如下所示:
ostream& X::print(ostream& os) {
return os << a << ' ' << b;
}
现在,read
函数应该做相反的事情:读取指定格式的内容(比如horse 54
,然后会产生a = "horse"
和b = 54
)。
假设输入不遵循此格式。我的直觉是,一旦我们遇到一个意想不到的字符(例如,在尝试读取int
时的一个字母),我们就会设置failbit
,将我们读取的每个字符都放回流中。在这种情况下,read
函数(或operator>>
)的预期行为是什么?标准库的行为如何?如果读取失败,是否应该要求我们撤消所有字符提取?
通常情况下,在失败的情况下,您应该将所涉及的任何对象保留为有效状态。这是否意味着回滚要写入的变量、部分写入变量或其他任何内容,取决于您试图实现的目标以及您认为对用户最有利的目标。在任何情况下,一定要记录您的选择,这样用户就可以进行编程,知道您的实现将如何运行。
正如Anton已经说过的那样,标准库似乎没有做出任何努力将字符重新放入流中。另一个似乎更接近您正在做的事情的实际示例是std::complex
类的operator>>
,它实际上必须在完成之前读取序列中的多个令牌。
template<typename _Tp, typename _CharT, class _Traits>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x)
{
_Tp __re_x, __im_x;
_CharT __ch;
__is >> __ch;
if (__ch == '(')
{
__is >> __re_x >> __ch;
if (__ch == ',')
{
__is >> __im_x >> __ch;
if (__ch == ')')
__x = complex<_Tp>(__re_x, __im_x);
else
__is.setstate(ios_base::failbit);
}
else if (__ch == ')')
__x = __re_x;
else
__is.setstate(ios_base::failbit);
}
else
{
__is.putback(__ch);
__is >> __re_x;
__x = __re_x;
}
return __is;
}
标准库在出现错误时从不尝试将字符放回流中。例如,以下是关于如何从流(27.7.2.2.2/2
)中读取short
的标准摘录:
operator>>(short& val);
转换就像由以下代码片段执行一样(使用与前一代码片段相同的符号):
typedef num_get<charT,istreambuf_iterator<charT,traits> > numget;
iostate err = ios_base::goodbit;
long lval;
use_facet<numget>(loc).get(*this, 0, *this, err, lval);
if (lval < numeric_limits<short>::min()) {
err |= ios_base::failbit;
val = numeric_limits<short>::min();
} else if (numeric_limits<short>::max() < lval) {
err |= ios_base::failbit;
val = numeric_limits<short>::max();
} else
val = static_cast<short>(lval);
setstate(err);
您可以看到,即使该数字不适合short
,也不会恢复任何内容。
相关文章:
- 如果没有malloc,链表实现将失败
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 视图中的参数推导失败:take_while
- 为什么istream不支持右值提取
- 将无符号char*转换为std::istream*C++
- 链接到自行创建的dll失败
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- GetShortPathName在网络驱动器上使用中文文件夹时失败
- gcc和c++17的过载解析失败
- 从 istream 读取 bitset<0> 总是失败?
- 检查 istream::read 和 istream::seekg 失败的最佳方法
- C++ istream:gcount() 是否总是在 read() 之后设置,即使它失败了
- 失败时,iStream 行为会在C++中更改
- C++ - 如果自定义提取器失败,如何恢复 istream
- 从istream读取自定义类型失败时的预期行为
- Istream提取操作符:如何检测解析失败
- 使失败并显示错误"cannot convert ‘std::istream {aka std::basic_istream<char>}’ to ‘bool’ in return"
- 使用istream迭代器时解析失败
- 从istream中提取失败后的字符串内容