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
. Кому выгодно это формальное неопределенное поведение и как?