libc++ std::istringstream 不会抛出异常。错误?

libc++ std::istringstream doesn't thrown exceptions. Bug?

本文关键字:错误 抛出异常 std istringstream libc++      更新时间:2023-10-16

在设置failbit时配置std::istringstream抛出异常后,我没有得到libc++发生的异常(这是在libcxxrt支持下编译的libc++的linux下)。我想这是libc++或libcxxrt:

中的错误。
#include <iostream>
#include <sstream>
template<typename T> std::istream &getvalue(std::istream &is, T &value, const T &default_value = T())
{
    std::stringstream ss;
    std::string s;
    std::getline(is, s, ',');
    ss << s;
    if((ss >> value).fail())
        value = default_value;
    return is;
}
int main()
{
    std::string s = "123,456,789";
    std::istringstream is(s);
    unsigned n;
    try
    {
        is.exceptions(std::ios::failbit | std::ios::eofbit);
        getvalue(is, n);
        std::cout << n << std::endl;
        getvalue(is, n);
        std::cout << n << std::endl;
        // Disable EOF exception on last bit
        is.exceptions(std::ios::failbit);
        getvalue(is, n);
        std::cout << n << std::endl;
        // Force Fail reading after EOF
        getvalue(is, n);
        std::cout << n << std::endl;
    }
    catch(std::ios::failure &fail)
    {
        std::cout << "Fail" << std::endl;
    }
}

libstdc++:

123
456
789
Fail

libc + +/libcxxrt输出:

123
456
789
0

编辑

也在OS x上测试过。

Bug提交:http://llvm.org/bugs/show_bug.cgi?id=15949

libc++正在响应27.7.2.1 [istream]/p4,其中描述了basic_istream解析operator>>unsigned:

如果其中一个被调用函数抛出异常,则unless另外明确指出,输入函数设置了错误的badbit状态。如果exceptions()中的badbit是on的,则输入函数会重新抛出异常而不完成其操作,否则不执行抛出任何东西并继续,就好像被调用的函数已经返回了故障指示。

如果:

is.exceptions(std::ios::failbit | std::ios::badbit);

,则获得期望的行为。

123
456
789
Fail

chico在下面的评论中正确地指出,他希望getline(is, s, ',')抛出,而不是unsigned提取器。

查看21.4.8.9 [string.][/p]/p7,它描述了getline:

Effects:作为一个未格式化的输入函数(27.7.2.3),除了对象的后续调用所返回的值不受影响basic_istream<>:: gcount()。在构建哨兵对象之后,如果Sentry转换为true,调用str.erase(),然后提取字符,并将它们追加到STR,就像调用Str.append (1, c),直到出现以下任意一个:…

所以问题变成了:

一个未格式化的输入函数如何表现?

27.7.2.3 [istream。无格式]/p1说:

每个未格式化的输入函数都通过构造一个带有默认参数noskipws (second)的类sentinel的对象。论点正确。如果哨兵对象返回true,当转换为bool类型的值,函数将努力获取所请求的数据输入。否则,如果哨兵构造函数通过抛出异常,或者如果哨兵对象返回false,则转换为bool类型的值,函数返回而不尝试获取任何输入。在这两种情况下,提取的字符数都设置为0;接受非零字符数组的未格式化输入函数size作为参数也应该存储一个空字符(使用charT())在数组的第一个位置。如果在然后输入ios::badbit在315在*this的错误状态。(从basic_ios<>::clear()抛出的异常不会被捕获或rethrown)。如果(exceptions()&badbit) != 0,则异常为rethrown。它还计算提取的字符数。如果没有异常时,将计数存储在成员中对象并返回指定的值。无论如何,哨兵对象在离开未格式化的输入函数之前被销毁。

315)这样做不会引发ios::失败。

(为了便于阅读,我加了强调)

因此,这似乎再次表明,如果希望从该解析操作中获得异常,则必须在exceptions中设置badbit