Search code examples
c++coding-stylereadability

Nice way of accessing member variables based on a switch


I'm working on code that contains several functions with the following pattern

memberType* var = NULL;
switch(someVariable)
{
  case 0: var = &object.MemberVariable1; break;
  case 1: var = &object.MemberVariable2; break;
  case 2: var = &object.MemberVariable3; break;
}

The member variables are of the same type. In some switches there are several dozen cases, which clutter up the function body with what's basically just data. I'd like to create an array, map or something similar so I could access the members based on the input value.

I'm thinking of having something like

sometype array[size] = {member1, member2, member3}

so the function could contain

memberType* var = array[index];

instead of the switch.

1. My first thought was creating a union in the class that contains the individual member variables and an array, so I can access either the individual members or access them via array + index. This is ugly, not apparent from the code at first glance and forces the member vars to be declared in a consecutive manner. It also does not allow me to access the same member variable for different indices.

2. Having an array that contains function pointers to functions that return individual member variables forces me to create tons of one line getter functions.

3. Having a statically allocated object so I can do something like

int offsets[size] = {
*(int*)&staticObject.member1 - *(int*)&staticObject,
*(int*)&staticObject.member2 - *(int*)&staticObject, 
*(int*)&staticObject.member3 - *(int*)&staticObject}

and use it

var = (memberType*)(*(int*)&object + offsets[index]);

is terrible.

Is there a nice way to get rid of this unnecessarily verbose pattern?

Disclaimer: I did not test the code used in the examples. It's just for illustration.


Edit: One important thing I forgot to mention: I don't want to change the size of the class because of serialization - I have yet to understand the implementation I'm working with.


Solution

  • You may want to check out pointers to members. This will allow you to implement your suggestion (3) more cleanly.

    Lets say your class looks like this.

    class X {
    public:
      memberType MemberVariable1;
      memberType MemberVariable2;
      memberType MemberVariable3;
    };
    

    Now we'll define an array of pointers to member variables.

    typedef memberType X::*MemberVar;
    MemberVar ptrs[3] = {
      &X::MemberVariable1,
      &X::MemberVariable2,
      &X::MemberVariable3
    };
    

    Then you can use the array like this.

    X obj;
    memberType var = obj.*(ptrs[index]);