How write *same* function to work with different elements of a struct

Jun 22, 2017 at 2:00pm

The struct in this case stores pixel data related to different components something like this:

typedef struct RGB
{
int blue;
int green;
int red;
} RGB;

RGB pixel_data[256][512];

The code processes the blue pixel data by accessing element blue, then doing same steps on element green and then on element red. I can write three different functions in which I access only pixel_data[y][x].blue then another function where pixel_data[y][x].green is accessed and finally one where pixel_data[y][x].red is accessed.

Since the three functions are very similar except these details, I am wondering if I can have a single function which can be called with a parameter specifying which color component to process. Is there a way to do this?

The struct is same for three functions so having void* is not needed. I could e.g use int* to pixel_data[y][x] and then do pointer arithmatic on that to access different components? Is this the best way to do this? Are there other ways?
Jun 22, 2017 at 2:27pm
How you write your function/s really depends on what the function/s are doing. But if you're function is just going to access one element of your pixel_data array at a time and the "math" is the same regardless of the color then you could just call the same function three times for each of the colors.

Jun 22, 2017 at 2:58pm
a (scoped) enum might be one alternative:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# include <iostream>

enum class Color {BLUE, GREEN, RED};

void tellColor (const Color& c)
{
    if(c == Color::BLUE)std::cout << "blue \n";
    if (c == Color::GREEN)std::cout << "green \n";
    if (c == Color::RED)std::cout << "red \n";
}

int main()
{
    auto c = Color::GREEN;
    tellColor(c);
}
Jun 22, 2017 at 5:31pm
c++ lets you declare structs like classes.

struct name
{
members;
};

name x

the old name at the end mess is a leftover from C that IMHO looks ugly and serves no function anymore.

Also, wouldn't RGB be bytes? I know of a few places where you might use more bits, like hyperspectral data, but most graphics and images still use 4 bytes (RGBA) format, so you are wasting a ton of memory if you don't need the extra space.

This isnt related to your issue, just a little cleanup that might help long term.


Also, for the dominate color issue ... I would use 1 byte for that also.
Just set it to 'r' 'g' or 'b'. Or you can do 1,2,4 and check it with a bitwise logic. Whatever you prefer. If you need the human output, you can do

char domcolor; //inside your struct maybe??

string colornames[3] = {"RED", "GREEN", "BLUE"};
... set domcolor as above if statements
..
cout << colornames[?.domcolor];

Something like that?

Last edited on Jun 22, 2017 at 5:38pm
Jun 22, 2017 at 6:15pm
three functions are very similar except these details


If you have something that is "similar except xxx", the most direct thing to consider if whether xxx can become a parameter.

There are a few ways to deal with that, but if you don't want to touch your struct, give member pointers a try:

They can be compile-time parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
struct RGB // don't typedef, that's gross
{
  int blue;
  int green;
  int red;
};
RGB pixel_data[256][512];

template<int(RGB::*PX)>
int inc_pixel(RGB& rgb) {
    return (rgb.*PX)++;
}

int main() {
  for(auto& row: pixel_data)
    for(RGB& px : row) {
      inc_pixel<&RGB::red>(px);
      inc_pixel<&RGB::green>(px);
      inc_pixel<&RGB::blue>(px);
      std::cout << " pixel is now " << px.red << ',' << px.green << ',' << px.blue << '\n';
    }
}


...or run-time parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
int inc_pixel(RGB& rgb, int RGB::*px) {
    return (rgb.*px)++;
}

int main() {
  for(auto& row: pixel_data)
    for(RGB& px : row) {
      inc_pixel(px, &RGB::red);
      inc_pixel(px, &RGB::green);
      inc_pixel(px, &RGB::blue);
      std::cout << " pixel is now " << px.red << ',' << px.green << ',' << px.blue << '\n';
    }
}




Last edited on Jun 22, 2017 at 6:17pm
Topic archived. No new replies allowed.