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.
 
    