Consider the following code:
#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;
}
Compiled under g++
with libstdc++
, the result is:
> g++ bitset_empty.cpp -o bitset_empty
> ./bitset_empty
before = 1
after = 1
Compiled under clang++
with libc++
, the result is:
> clang++ -stdlib=libc++ bitset_empty.cpp -o bitset_empty
> ./bitset_empty
before = 1
after = 0
Which one is right? Both (because of undefined behavior)? GCC? Clang?
From my understanding, libc++ is right here, but it's not the only correct behavior.
N4140 §20.6.4 [bitset.operators]
Effects: Extracts up to N characters from is. Stores these characters in a temporary object str of type
basic_string<charT, traits>
, then evaluates the expressionx = bitset<N>(str)
. Characters are extracted and stored until any of the following occurs:
- N characters have been extracted and stored;
- end-of-file occurs on the input sequence;
- the next input character is neither
is.widen(’0’)
noris.widen(’1’)
(in which case the input character is not extracted).If no characters are stored in
str
, callsis.setstate(ios_base::failbit)
(which may throwios_base::failure
(27.5.5.4))
It's important to note that x = bitset<N>(str)
is not conditional. If ios_base::failure
is not thrown, then that is the expression executed. And bitset<N>(""s)
(that is, of an empty string) is 0
.
Thus, in my understanding, your bitset
should be zeroed or the aforementioned exception should've been thrown.
If no exception is thrown, you may want to test if your operation was successful (by testing the returned stream).