Я использую STB библиотека для загрузки изображений в память. Конкретная функция, stbi_load
, возвращает указатель на unsigned char
, который является массивом.
Я испытываю желание использовать новый C ++ 17 API для необработанных данных, std::byte
, который позволил бы мне быть более выразительным, и позволил бы мне псевдоним необработанных данных пиксель за пикселем или цвет за цветом, приведя его к другому типу данных (целые числа разного размера).
Теперь я попробовал это:
std::unique_ptr<std::byte[], stbi_deleter>(stbi_load(...));
Конечно, это не сработало из-за отсутствия неявного преобразования.
Тогда я попробовал это:
std::unique_ptr<std::byte[], stbi_deleter>(
static_cast<std::byte*>(stbi_load(...))
);
Опять же, это все еще не сработало. Я должен был решить использовать reinterpret_cast
вместо. И заставил меня задаться вопросом, является ли это преобразование законным или нет. Могу ли я законно преобразовать unsigned char*
в std::byte*
в соответствии со строгим правилом алиасинга? И тогда я могу привести данные к другому типу данных, как std::uint32_t*
и мутировать это? Это также нарушит правило наложения имен?
Строгое правило псевдонимов никогда не запрещает какие-либо преобразования указателей. Речь идет о типе выражения, обращающегося к объекту.
std::byte
может быть псевдонимом любого другого типа, это упомянуто на странице cppreference, на которую вы ссылаетесь, а также в строгом правиле псевдонимов в стандарте (C ++ 17 basic.lval / 8.8). Так что это нормально использовать reinterpret_cast<std::byte *>
а затем читать или писать массив unsigned char
,
Если вы используете выражение типа uint32_t
читать или писать массив unsigned char
, что будет нарушать строгое правило алиасинга.
Могу ли я на законных основаниях преобразовать беззнаковый char * в std :: byte * в соответствии со строгим правилом алиасинга?
Да, именно поэтому std::byte
«наследует» от unsigned char
, Но вы должны пройти reinterpret_cast<>
так же, как вы должны при приведении произвольного типа к char*
или же unsigned char*
И затем я могу привести данные к другому типу данных, например std :: uint32_t *, и изменить его.
Вы не можете ничего сделать с std::byte
что вы не можете с char*
или же unsigned char*
,
Главное std::byte
кажется полезным, чтобы иметь функции, которые могут иметь как строковые, так и необработанные перегрузки.
Кроме того, он избавляется от следующего раздражения:
char val = foo();
std::cout << (int)val << "\n";