views:

49

answers:

3

So I have an object called Vertex which contains some parameters (let's call them sx, sy and i). sx, sy and i each have special setters: ie, Vertex looks something like

class Vertex {
    public:
        float sx() { return sx; };

        void setSx(float val) {
            val > 0 ? sx = val : sx = 0;
        };

        float sy() { return sy; };

        void setSy(float val) {
            val >= 0 ? sx = val * 0.5 : sx = -val;
        };

        float i() { return i; };

        void setI(float val) { i = val; };

    private:
        float sx, sy, i;
};

I would like to be able to iterate through a Vertex's parameters without having to call each setter. For example:

Vertex* v = new Vertex();
for (int i = 0; i < Vertex::size; i++)
    (*v)[i] = 0;

or something like that, instead of having to use the clunkier notation:

Vertex* v = new Vertex();
v->sx = 0;
v->sy = 0;
v->i = 0;

Is there any way to accomplish this in a more elegant way than just overloading operator[] and using a switch statement? I don't need to use the exact notation I demonstrated above, I just need a way to iterate through the components of a Vertex without caring about the custom setters of each of them.

+2  A: 

You could create an array of pointers to floats, and index off that, but I'm not sure if the result would qualify as "most elegant"

class Vertex { 
      float* varptr[3];
    public: 
        Vertex ()
        {
              varptr[0] = &(this.sx);
              varptr[1] = &(this.sy);
              varptr[2] = &(this.i);
         }
         float& operator[](int n)
         {
               return *varptr[n];
         }
James Curran
Since sx, sy and i are only accessed through methods they just need to be in the array. There is no need to have an array of pointers to members aswell.
Martin York
Notice that this will make it need a copy constructor and copy assignment operator to work (as opposed to @Martin's solution and the initial class by questioner).
Johannes Schaub - litb
+2  A: 

How about a reset method().
Or just do it in the constructor so when you create it the object is correctly initialized.

Martin York
+3  A: 

Stealing from James Curran (and adapting slightly):

(James if you want to claim this method I will delete). :-)

class Vertex {
  public:
    float sx() const        {return data[0];}
    float sy() const        {return data[1];}
    float i()  const        {return data[2];}

    void setSx(float val)   {data[0] = val >  0 ? val       : 0;   }
    void setSy(float val)   {data[1] = val >= 0 ? val * 0.5 : -val;}
    void setI(float val)    {data[2] = val;                        }

    float& operator[](int n)
    {
           return data[n];
    }

    float const& operator[](int n) const
    {
           return data[n];
    }

    static std::size_t size() {return 3;}

  private:
    float data[3];
};
Martin York
@Andreas: Where do you see that in the question?
Georg Fritzsche
Hmm... Now, why didn't I see that..... (BTW, the least you coulda done is up-voted me....)
James Curran
@James Curran: Copy and post this into your answer and I will delete this.
Martin York
@Martin: No. The key was was your insight.... You deserve it..
James Curran