Here is a simple example of what I'm trying to achieve: Assume we are given a std::vector<std::byte> rgb_data
containing RGB color values and a struct rgb{ double r, g, b; };
. I would to create a std::vector<rgb> transformed_rgb_data
containing these RGB color values using std::transform
. Without std::transform
, this could be done as follows:
std::size_t j = 0;
for (std::size_t i = 0; i < rgb_data.size(); i = 3)
{
transformed_rgb_data = {
static_cast<double>(rgb_data[i],
static_cast<double>(rgb_data[i 1],
static_cast<double>(rgb_data[i 2]
};
}
Is there a mechanism in the standard library which allows me to construct an iterator for rgb_data
which increments by 3
and references a std::tuple
(I think that would be the best idea) which then is passed to the unary function passed to std::transform
?
CodePudding user response:
The c 23 way would be by using std::views::adjacent_view
(and its friend std::views::adjacent_transform_view
), which is doing exactly this but not many compilers are currently supporting it.
CodePudding user response:
- Create your own custom "RGB view" iterator that has an internal
uint8_t* p
pointer. - When dereferenced, use the 3 adjacent bytes to construct the RGB struct and return it (something like
RGB{p[0], p[1], p[2]}
). - When incremented, increment the pointer by 3.
- Make sure to specialize
std::iterator_traits
for your iterator - Copy that into your RGB vector
std::vector<uint8_t> byteArray = ...;
std::vector<RGB> rgbArray(rgbaIter{byteArray.data()},
rgbaIter{byteArray.data() byteArray.size()});
// Can also use vector::insert, std::copy, std::copy_n, etc.