C ++ Index Class Members

I have a class vector

class vector3f
{
public:
float x;
float y;
float z;
};

      

If I want to access one of the members, I need to enter vec.x, vec.y and vec.z. Now I have an algorithm that is supposed to access data members per index, for example:

for(int i = 0; i < 3; i++)
{
vec[i] = i*i;
}

      

Doing this without an index will result in multiple if-conditions:

for(int i = 0; i < 3; i++)
{
if(i == 0){vec.x = i*i;}
else if(i == 1){vec.y = i*i;}
else if(i == 2){vec.z = i*i;}
}

      

Is there a way to index data items so that they are resolved at compile time? I don't want to use an array in a vector class because accessing data members with vec.x, vec.y and vec.z is more programmer friendly. What would be the best solution to avoid these if-conditions?

+3


source to share


3 answers


You can overload operator[]

for your class to localize those conditions if

(or preferably a switch

) in one place:

class vector3f
{
public:
  float x;
  float y;
  float z;

  float& operator[] (size_t i)
  {
    switch (i) {
      case 0: return x;
      case 1: return y;
      case 2: return z;
      default: throw "something";
    }
  }

  float operator[] (size_t i) const
  { return (*const_cast<vector3f*>(this))[i];
}

      

This is a common and safe way to do this.

If your class is in fact a standard layout class 1 as you showed, and if you know the alignment and padding scheme of your compiler / platform, and if you know from them what float

will just sit back and forth in memory, you can also implement this operator:



float& operator[] (size_t i)
{
  return (&x)[i];
}

      

This refers to x

how the beginning of the float

s array . It will be faster, but relies on the ifs I mentioned above and does not do bounds checking.


1 Which basically means it has no non-empty base classes, no features, virtual

and no data item of type custom layout.

+5


source


Not really at compile time, but you can optimize.

You can use a pointer-member variable and then an array of it. Start with:

float vector3f::*px;
px = &vector3f::x;
(vec.*px) = 10.2;

      

Then you declare an array of pointer to element:

float vector3f::*pArray[3];

      



Assign them:

pArray[0] = &vector3f::x;
pArray[1] = &vector3f::y;
pArray[2] = &vector3f::z;

      

Use them:

(vec.*pArray[0]) = 10.2; // This is vector3f::x
(vec.*pArray[1]) = 1042.5; // This is vector3f::y

      

And change the loop body accordingly to index the corresponding element pointer!

+1


source


An interesting alternative can be obtained using references .

class vector3f
{
public:
  float &x, &y, &z;
  float value[3];

  vector3f() :
    x(value[0]), y(value[1]), z(value[2]){}
};

      

Here we bind x to value [0], y to value [1], and z to value [2] - these are aliases for array entries, but note that they allocate an extra 4 bytes per class reference. This way we can name our array for ease of user access.

We can also avoid calling the overloaded runtime operator [

(but a good compiler should have built-in access, switch / case access anyway).

Usage example:

vector3f test;
test.value[0] = 227.f;
test.value[1] = 42.f;
test.value[2] = -1.f;
printf("Values are %lf, %lf and %lf.",test.x,test.y,test.z);

      

Resulting output:

Values are 227.000000, 42.000000 and -1.000000.

      

0


source







All Articles