简体   繁体   中英

Replace pointer arithmetic with std::span

I have the following code that uses pointer arithmetic and would like to replace it using std::span (or, I suppose, gsl::span ). The code iterates over a number of pixels, each represented by 4 contiguous bytes, and updates their blue and green colours.

auto* row = (uint8_t*)buffer->data;
for (auto y = 0; y < buffer->height; ++y) {
    auto* pixel = (uint32_t*)row;
    for (auto x = 0; x < buffer->width; ++x) {
        auto blue = x + blueOffset;
        auto green = y + greenOffset;
        *pixel++ = ((green << 8) | blue);
    }
    row += buffer->pitch;
}

buffer->data is a void* returned from a call to Windows VirtualAlloc(...) function.

How can this code be written to use safe, modern C++, such as std::span , as suggested by the C++ Core Guidelines and Moderns C++ ?

This compiles with each of C++20, gsl and gsl-lite. As you didn't provide a reproducible example I didn't test or benchmark this solution.

    auto const my_span = span{
        reinterpret_cast<uint8_t *>(buffer->data),
        buffer->height * buffer->pitch};
    constexpr auto size_ratio = sizeof(uint32_t) / sizeof(uint8_t); // 4
    auto const uint8_width = size_ratio * buffer->width;

    auto row_offset = 0UL;
    auto row = my_span.subspan(row_offset, buffer->width);
    for (auto y = 0; y < buffer->height; ++y) {
        auto const pixels = span{
            reinterpret_cast<uint32_t *>(row.data()),
            buffer->width};
        auto pixel = pixels.begin();
        for (auto x = 0; x < buffer->width; ++x) {
            auto const blue = x + blueOffset;
            auto const green = y + greenOffset;
            *pixel++ = ((green << 8) | blue);
        }
        row_offset += buffer->pitch;
        row = my_span.subspan(row_offset, uint8_width);
    }

Obviously using spans here doesn't necessarily make the code easier to read due to interpreting the same memory both as uint8_t and uint32_t . The spans should still give more safety.

The code could be made easier to read by providing more members or member functions in the struct which is pointed at by buffer . Eg member functions could provide you with the needed subspans or at least with uint8_width . As this wasn't asked, I didn't touch that struct here. It might be given by a library, but one could still write a wrapper in that case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM