I am trying to pack multiple indices into a byte (as defined by the GIF format):
std::uint8_t global_color_table_flag; // bit [0]
std::uint8_t color_resolution; // bits [1-3]
std::uint8_t sort_flag; // bit [4]
std::uint8_t global_color_table_size; // bits [5-7]
I wanted to use
std::uint8_t field = (global_color_table_flag << 7) |
(color_resolution << 4) | (sort_flag << 3) |
(global_color_table_size);
but the left shift operator <<
promotes my std::uint8_t
to int
and the compiler complains (-Werror
). Why is that so? Using it on an int
does not promote it to a bigger int
. It is just UB if you use it incorrectly to my understanding. Why is std::uint8_t
any different?
If I use std::byte
, the behavior is as expected. However, the code is rather ugly because of the issue mentioned above:
std::byte global_color_table_flag_byte{global_color_table_flag};
global_color_table_flag_byte <<= 7;
std::byte color_resolution_byte{color_resolution};
color_resolution_byte <<= 4;
std::byte sort_flag_byte{sort_flag};
sort_flag_byte <<= 3;
std::byte global_color_table_size_byte{global_color_table_size};
std::byte packed_field = global_color_table_flag_byte |
color_resolution_byte | sort_flag_byte |
global_color_table_size_byte;
file_stream << std::to_integer<std::uint8_t>(packed_field);
Is there a better way to proceed? As a side question, why can't I just write my std::byte
to my binary stream? I thought the whole point of this type was to facilitate manipulation of such streams.