libstdc++ 和 libc++ 之间的行为差​​异:位集上的运算符>>

Vin*_*ent 5 c++ gcc std clang std-bitset

考虑以下代码:

#include <bitset>
#include <sstream>
#include <iostream>

int main(int argc, char* argv[])
{
    std::stringstream stream;
    std::bitset<1> bitset(1);
    std::cout<<"before = "<<bitset[0]<<std::endl;
    stream<<"4";
    stream>>bitset;
    std::cout<<"after = "<<bitset[0]<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++在下编译libstdc++,结果为:

> g++ bitset_empty.cpp -o bitset_empty
> ./bitset_empty 
before = 1
after = 1
Run Code Online (Sandbox Code Playgroud)

clang++在下编译libc++,结果为:

> clang++ -stdlib=libc++ bitset_empty.cpp -o bitset_empty
> ./bitset_empty 
before = 1
after = 0
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?两者(因为未定义的行为)?海湾合作委员会?铛?

krz*_*zaq 3

根据我的理解,libc++ 就在这里,但它不是唯一正确的行为。

\n\n
\n

N4140 \xc2\xa720.6.4 [位集.运算符]

\n\n

效果:从 is 中提取最多 N 个字符。将这些字符存储在类型为 的临时对象 str 中basic_string<charT,\n traits>,然后计算表达式x = bitset<N>(str)。\n 提取并存储字符,直到发生以下任一情况:

\n\n
    \n
  • N个字符已被提取并存储;
  • \n
  • 文件结尾出现在输入序列上;
  • \n
  • 下一个输入字符既不是is.widen(\xe2\x80\x990\xe2\x80\x99)也不是is.widen(\xe2\x80\x991\xe2\x80\x99)(在这种情况下不提取输入字符)。
  • \n
\n\n

如果 中没有存储字符str,则调用\n is.setstate(ios_base::failbit)(可能会抛出ios_base::failure\n (27.5.5.4))

\n
\n\n

值得注意的是,这不是x = bitset<N>(str)有条件的。如果ios_base::failure没有抛出,那么这就是执行的表达式。并且bitset<N>(""s)(即空字符串)是0

\n\n

因此,根据我的理解,您bitset应该归零,或者应该抛出上述异常。

\n\n

如果没有抛出异常,您可能需要测试操作是否成功(通过测试返回的流)。

\n