В приведенном ниже коде переменная типа перечисления сохраняется в битовом поле. Насколько я понимаю, переменная может быть извлечена без потери данных. Однако это не сработает.
Соответствует ли приведенная ниже мощность стандарту?
#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): «Размер наименьшего битового поля достаточно большой, чтобы вместить
все значения типа перечисления max (M, 1), если b min равно нулю ... ".
[class.bit] (4)
«Значение перечислителя сохраняется в битовом поле того же
тип перечисления и количество битов в битовом поле достаточно велики
хранить все значения этого типа перечисления (10.2), оригинал
значение перечислителя и значение битового поля
сравнивать равные. "
Если так, то почему вывод выглядит так?
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: добавлен static_cast <> (), так что код компилируется с заменой 'enum class' на простой 'enum'.
При использовании простого enum вместо enum class вывод будет таким, как ожидалось. Кроме того, с одним дополнительным битом в битовом поле вывод будет таким, как ожидалось.