6

在将 a 配置为在设置std::istringstream时抛出异常后,failbit我没有发现 libc++ 发生异常(这是在 linux 下,在 libcxxrt 的支持下编译的 libc++)。我想这是 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 上进行了测试。

提交的错误: http://llvm.org/bugs/show_bug.cgi?id= 15949

4

1 回答 1

4

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

如果这些被调用函数之一引发异常,则除非另有明确说明,否则输入函数会将 badbit 设置为错误状态。如果 badbit 在 exceptions() 中打开,则输入函数会在不完成其操作的情况下重新抛出异常,否则它不会抛出任何东西并继续进行,就好像被调用的函数返回了失败指示一样。

如果:

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

然后获得所需的行为。

123
456
789
Fail

更新

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

查看描述此内容的 21.4.8.9 [string.io]/p7 getline

效果:表现为未格式化的输入函数 (27.7.2.3),除了它不影响后续调用 basic_istream<>::gcount() 时返回的值。构造一个 sentry 对象后,如果 sentry 转换为 true,则调用 str.erase(),然后从 is 中提取字符并将它们附加到 str,就像通过调用 str.append(1, c) 一样,直到发生以下任何情况: 。 ..

于是问题就变成了:

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

27.7.2.3 [istream.unformatted]/p1 说:

每个未格式化的输入函数通过使用默认参数 noskipws(第二个)参数 true 构造一个类哨兵对象开始执行。如果 sentry 对象返回 true,则在转换为 bool 类型的值时,该函数会努力获取请求的输入。否则,如果哨兵构造函数因抛出异常而退出,或者哨兵对象返回 false,则当转换为 bool 类型的值时,函数将返回而不尝试获取任何输入。在任何一种情况下,提取的字符数都设置为 0;以非零大小的字符数组作为参数的未格式化输入函数还应在数组的第一个位置存储一个空字符(使用 charT())。如果在输入期间抛出异常,则 ios::badbit 开启315在 *this 的错误状态。(从 basic_ios<>::clear() 抛出的异常不会被捕获或重新抛出。)如果 (exceptions()&badbit) != 0 则重新抛出异常。它还计算提取的字符数。如果没有抛出异常,则通过将计数存储在成员对象中并返回指定的值来结束。无论如何,哨兵对象在离开未格式化的输入函数之前被销毁。

315) 这样做不会导致 ios::failure 被抛出。

(出于可读性目的,我添加了重点)

因此,这似乎再次表明,如果此解析操作需要异常,badbit则必须在exceptions.

于 2013-05-10T01:40:19.710 回答