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* ppointer. - 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_traitsfor 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.
