std::byte из С++ 17 требуется класс перечисления:
enum class byte : unsigned char {};
Мы можем использовать этот std::byte для представления необработанной памяти вместо одного из char поскольку она более безопасна для типов, имеет определенные байтовые операторы и не может продвигать int из синего, как char. Нам нужно использовать явные приведения или to_integer для преобразования std::byte в другие целые числа. Однако из множества источников мы все равно получаем char (или, скорее всего, целые буферы char) и поэтому можем его конвертировать:
void fn(char c)
{
std::byte b = static_cast<std::byte>(c);
// ... that may invoke undefined behavior, read below
}
Подпись char определяется реализацией, поэтому std::numeric_limits<char>::is_signed может быть true. Поэтому выше c может иметь отрицательные значения, которые находятся вне диапазона unsigned char.
Теперь в стандарте С++ 17 в пункте 8.2.9 Static cast [expr.static.cast] мы можем прочитать, что:
Значение интегрального или перечисляемого типа может быть явно преобразовано в полный тип перечисления. Значение не изменяется, если исходное значение находится в пределах диапазона значений перечисления (10.2). В противном случае поведение не определено.
А из 10.2 видно, что указанный диапазон - это диапазон базового типа. Поэтому, чтобы избежать неопределенного поведения, мы должны написать больше кода. Например, мы можем добавить приведение к unsigned char для достижения определенных эффектов модульной арифметики во время трансляции:
void fn(char c)
{
std::byte b = static_cast<std::byte>(static_cast<unsigned char>(c));
// ... now we have done it in portable manner?
}
Я что-то неправильно понял? Разве это не слишком сложно и ограничительно? Почему enum class который имеет неподписанный базовый тип, следует за модульной арифметикой, как это делает его базовый тип? Обратите внимание, что вся строка приводов, скорее всего, не компилируется компилятором. char, когда он подписан должен быть два дополнением, так как С++ 14 и поэтому его побитовое представление должно быть такими же, как после модульного арифметического преобразования в unsigned char. Кому выгодно это формальное неопределенное поведение и как?