2

I have a structure with similarly named variables such as

char        c1;
char        c2;
char        c3;
char        c4;
char        c5;
char        c6;
char        c7;
char        c8;

What I need is a loop that compares an input with each.

//Something Like
for(int i = 1; i <= 8; i++) {
    if(compared == foo->c(i)) {
        return compared;
    }
}

Right now I have a long list of if and elses. I cannot change the struct unfortunately. If the long string of if/elses are the most effective way of doing it (performance not how good the code looks) then Ill just keep it like that.

I basically want a loop that changes the variable name that I am currently comparing to make the code less messy and hopefully faster.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 7
    If all those elements are of the same type, why not use an array instead? Or a map? What's the purpose of those similarly named members? – Some programmer dude Nov 19 '18 at 14:58
  • 2
    Depending on the problem/code an array like `char c[8]` might better fit your needs. Take care, array indizes start at 0, so `c1` would then be `c[0]`. – Werner Henze Nov 19 '18 at 14:59
  • There is no way to do what you're asking without reflection, which C++ does not support. – Arnav Borborah Nov 19 '18 at 15:03
  • 1
    Maybe this: https://stackoverflow.com/a/25953607/487892 if you can't change the poor design decision. – drescherjm Nov 19 '18 at 15:04
  • @Someprogrammerdude Yeah, but the struct was made years ago and is compliant to a standard so I definitely wont be able to change it to anything else. Even if it would be efficient. – Cristian Camilo Cabrera Nov 19 '18 at 15:12

2 Answers2

9

Well, since you can't change the structure, you can avoid some repetition and work around the requirment by using an array of pointers to the fields:

char const * c_ptr[] = {
  &foo->c1, &foo->c2, &foo->c3, /* ... */, &foo->c8
};

Making your loop into this:

for(int i = 0; i < 8; ++i) {
    if(compared == *c_ptr[i]) {
        return compared;
    }
}

But really, try to push for changing the structure if at all possible.


An alternative option, given this is C++, is to use pointers to members. Which has the added benefit of making the array constexpr (known entirely at compile time). So for instance, this code ...

static constexpr char Foo:: *c_ptr [] = {
    &Foo::c1, &Foo::c2, &Foo::c3, &Foo::c4,
    &Foo::c5, &Foo::c6, &Foo::c7, &Foo::c8
};

for(int i = 0; i < 8; ++i) {
    if(compared == foo->*c_ptr[i]) {
        return compared;
    }
}

... can be successfully optimized to an unrolled loop, equivalent to a sequence of branches.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

You can use a std::reference_wrapper with char as the template parameter.

Then your will code will look like this:

#include <functional>

using charRef = std::reference_wrapper<char>;
struct Foo {
    char c1, c2, c3, c4, c5, c6, c7, c8;
};

char processFoo(Foo& f, char compared) {    
    charRef CR[] = {f.c1, f.c2, f.c3, f.c4, f.c5, f.c6, f.c7, f.c8};
    for(int i = 0; i < 8; ++i) {
        if(compared == CR[i]) {
            return compared;
        }
    }
    return '\0';
}
P.W
  • 26,289
  • 6
  • 39
  • 76