能否为std::vector创建步长为3的迭代器以适配std::transform?
使用std::transform处理连续RGB字节数据的方案
标准库本身没有直接提供这种“步长为3、解引用返回tuple”的迭代器,但有两种可行方案实现你的需求:
方案一:C++23 用std::views::chunk(最简洁)
C++23引入的std::views::chunk可以直接将连续容器分成固定大小的子范围块,完美适配你的场景,不需要自定义迭代器:
#include <vector> #include <cstddef> #include <byte> #include <algorithm> #include <ranges> struct rgb { double r, g, b; }; int main() { std::vector<std::byte> rgb_data = {/* 填充你的RGB字节数据 */}; std::vector<rgb> transformed_rgb_data; // 提前预留空间避免频繁扩容 transformed_rgb_data.reserve(rgb_data.size() / 3); std::ranges::transform( // 将rgb_data按每3个元素分块 rgb_data | std::views::chunk(3), std::back_inserter(transformed_rgb_data), [](const auto& chunk) { // 从块中取出三个字节,转换为double后构造rgb对象 return rgb{ static_cast<double>(std::to_integer<std::uint8_t>(chunk[0])), static_cast<double>(std::to_integer<std::uint8_t>(chunk[1])), static_cast<double>(std::to_integer<std::uint8_t>(chunk[2])) }; } ); }
注意:要确保rgb_data的元素个数是3的倍数,否则最后一个块的元素会不足3个,此时需要额外判断处理。
方案二:自定义块迭代器(兼容C++11及以上)
如果无法使用C++23,可以自己实现一个简单的迭代器,每次前进3步,解引用时返回包含三个转换后值的tuple:
#include <vector> #include <cstddef> #include <byte> #include <algorithm> #include <iterator> #include <tuple> #include <utility> struct rgb { double r, g, b; }; template <typename Iterator> struct RGBChunkIterator { // 迭代器关联类型定义 using value_type = std::tuple<double, double, double>; using reference = value_type; using pointer = value_type*; using difference_type = std::ptrdiff_t; using iterator_category = std::input_iterator_tag; explicit RGBChunkIterator(Iterator it) : it_(std::move(it)) {} // 解引用时返回包含三个通道值的tuple reference operator*() const { return { static_cast<double>(std::to_integer<std::uint8_t>(*it_)), static_cast<double>(std::to_integer<std::uint8_t>(*(std::next(it_, 1)))), static_cast<double>(std::to_integer<std::uint8_t>(*(std::next(it_, 2)))) }; } // 前置递增:前进3步 RGBChunkIterator& operator++() { std::advance(it_, 3); return *this; } // 后置递增 RGBChunkIterator operator++(int) { auto temp = *this; std::advance(it_, 3); return temp; } // 相等/不等判断 bool operator==(const RGBChunkIterator& other) const { return it_ == other.it_; } bool operator!=(const RGBChunkIterator& other) const { return !(*this == other); } private: Iterator it_; }; int main() { std::vector<std::byte> rgb_data = {/* 填充你的RGB字节数据 */}; std::vector<rgb> transformed_rgb_data; transformed_rgb_data.reserve(rgb_data.size() / 3); std::transform( RGBChunkIterator(rgb_data.begin()), RGBChunkIterator(rgb_data.end()), std::back_inserter(transformed_rgb_data), [](const auto& color_tuple) { // 将tuple转换为rgb结构体 return rgb{ std::get<0>(color_tuple), std::get<1>(color_tuple), std::get<2>(color_tuple) }; } ); }
同样需要保证rgb_data的元素个数是3的倍数,避免越界访问。
内容的提问来源于stack exchange,提问作者0xbadf00d
相关产品推荐
相关产品推荐

