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

时间:2013-05-09 18:06:47

标签: c++ language-lawyer libc++

配置std::istringstream以在设置failbit时抛出异常后,我发现libc ++没有异常(这是在Linux下使用libc ++编译并在libcxxrt的支持下编译)。我想这是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

1 个答案:

答案 0 :(得分:4)

libc ++正在回应27.7.2.1 [istream] / p4,它描述了basic_istream的{​​{1}}解析operator>>

  

如果其中一个被调用的函数抛出异常,则除非   另外明确指出,输入函数设置错误的badbit   州。如果在exceptions()中打开了badbit,则输入函数会重新生成   没有完成其动作的异常,否则它不会   抛出任何东西并继续进行,好像被调用的函数已返回a   失败指示。

如果:

unsigned

然后获得所需的行为。

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

<强>更新

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

查看描述此unsigned的21.4.8.9 [string.io] / p7:

  

效果:表现为无格式输入功能(27.7.2.3),除外   它不会影响后续调用返回的值   basic_istream&LT;&GT; :: gcount的()。构建一个岗哨对象后,如果   sentry转换为true,调用str.erase()然后提取   from中的字符并将它们附加到str,就好像通过调用一样   str.append(1,c)直到发生以下任何一种情况:...

所以问题就变成了:

  

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

27.7.2.3 [istream.unformatted] / p1说:

  

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

     

315)这样做不会导致ios ::失败。

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

所以这再次表明如果需要从此解析操作中获得异常,则必须在getline中设置badbit