Daily bit(e) C++. Работа с массивами в стиле C, используя std::span
Добавлено 30 июля 2026 в 02:06
Daily bit(e) C++ 53, безопасное обертывание массивов в стиле C с помощью std::span из C++20.

Передача данных в виде массивов в стиле C может быть неизбежной при взаимодействии с устаревшим кодом или API на C. Это может привести к ошибкам при отслеживании размера массива.
В C++20 был представлен std::span, представление, которое может обернуть непрерывный блок памяти в интерфейс диапазона. Это позволяет нам безопасно использовать алгоритмы и представления для обработки данных без копирования их в контейнер C++.
std::span также может быть преобразован в std::span или std::byte, предоставляя доступ к представлению базового объекта.
#include <cstdint>
#include <span>
#include <vector>
#include <ranges>
#include <utility>
#include <print>
size_t read(char* buffer, size_t size);
int get_data(char** buffer, size_t* size);
int main()
{
char buffer[16];
auto view = std::span(buffer);
// Вызов C API, используя обернутый буфер
size_t cnt = read(view.data(), view.size());
// Обработка суб-представления на основе количества фактически прочитанных байтов
for (auto v : view.subspan(0, cnt))
std::print("{} ", v);
// напечатает: a b c d
char* buff;
size_t length;
int ret = get_data(&buff, &length);
if (ret != 0)
return ret;
// Обернуть C буфер в a std::span
auto buffer_view = std::span(buff, length);
// std::span работает как любой другой диапазон,
// например, обратная итерация:
for (auto it = buffer_view.rbegin(); it != buffer_view.rend(); ++it)
{
}
// или комбинирование с представлениями:
for (auto v : buffer_view | std::views::drop(8))
std::print("{} ", v);
// напечатает: i j k l m n o p
struct Data {
int x;
int y;
};
std::vector<Data> data{{2,3},{1,5},{4,4}};
// Доступ к базовому представлению:
std::span<std::byte> bytes = std::as_writable_bytes(std::span(data));
std::print("0x");
for (auto v : bytes)
std::print("{:x}", std::to_underlying(v));
// напечатает: 0x200030001000500040004000
std::println("");
}
size_t read(char* buffer, size_t size)
{
size_t cnt = size >= 4 ? 4 : size;
for (size_t i = 0; i < cnt; ++i)
buffer[i] = 'a'+i;
return cnt;
}
int get_data(char** buffer, size_t* size)
{
static char buff_[16]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
*buffer = buff_;
*size = 16;
return 0;
}
