In the code below, a variable of enumeration type is saved into a bit-field. As I understand it, variable can be retrieved without data loss. However, that doesn't work.
Is the output below in accordance with the standard?
#include<iostream>
using namespace std;
const int M=3, UL=(1<<M)-1; // range 0 .. 7, fits into 3 bits
enum class ec { e_min=0, e_max=UL};
// in [decl.enum] (8): b_min==0 && b_max==7==2^M-1
struct bitFieldType {
ec data : M; // 3 bits
};
int main(){
bitFieldType bf;
for (int c=0; c<=UL; ++c){;
ec enumIn { static_cast<ec>(c) }; // initialize enumeration type
bf.data = enumIn; // copy into bit-field
ec enumOut{bf.data}; // retrieve enumeration type from bit-field
cout<<static_cast<int>(enumIn) <<" "<< static_cast<int>(enumOut)
<< " " << (bf.data==enumIn) <<"\n";
}
}
[dcl.enum] (8): "The size of the smallest bit-field large enough to hold all the values of the enumeration type is max(M, 1) if b min is zero ... ." [class.bit] (4) " the value of an enumerator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type (10.2), the original enumerator value and the value of the bit-field shall compare equal."
If so, why does output look like this?
clang++ -Wall -fsanitize=undefined -pedantic -std=c++17 bitf.cpp && ./a.out
0 0 1
1 1 1
2 2 1
3 3 1
4 -4 0
5 -3 0
6 -2 0
7 -1 0
clang++ --version
clang version 9.0.0 (trunk 351995)
Target: x86_64-unknown-linux-gnu
EDIT: added a static_cast<>() such that the code compiles with 'enum class' replaced by plain 'enum'.
With plain 'enum' instead of 'enum class', the output is as expected. Also, with one extra bit in the bit-field, the output is as expected.