Home > Back-end >  Can we create an iterator for a `std::vector` which increments over three values simultaneously?
Can we create an iterator for a `std::vector` which increments over three values simultaneously?

Time:11-08

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.
  • Related