c++member-variables

"Rename" member variables in derived classes


The question may seem a little bit weird but I'll try to contestualize a little bit the use case.

Suppose you have a generic implementation of a two-dimensional (Cartesian) field with dimensions dim1 and dim2, coordinates c1 and c2.

struct Field2D {
  struct size_type {
     size_t dim1,dim2;
  };
  struct coordinates {
     size_t c1,c2;
  }
Field2D(size_type const & siz) : size_(siz), data(size_.dim1*size_.dim2) {}
double get(coordinates const & coords) {
  return data_[coords.c1*size_.dim2 + coords.c2];
}
//Other methods
private:
  size_type size_;
  vector<double> data_;
};

You want to inherit from this class but you want to be more explicit about the nature of the coordinates. For example, a field PositionVersusTime whose coordinates are "x" and "t" and dimensions "nx" and "nt", whose usage I'd like to be

int main(){
   PositionVersusTime::size_type siz;
   siz.nx = 5;
   siz.nt = 2;
   PositionVersusTime myField(siz);
   PositionVersusTime::coordinates coords;
   coords.x = 2;
   coords.t = 0;
   auto out = myField.get(coords);
   return 0;
}

The reason I want to do this is that the ordering may change depending on the field (for example a TimeVersusPosition) and sometimes "forgotten" by the user. Is there a way to obtain a similar behavior? or should I simply go with getters (e.g., coords.x() = 2) ?


Solution

  • Combining others solutions and using inheritance and reference data members, here is my solution.

    Notice slight changes to the Field2D variable types.

    struct size_type{
        size_t dim1, dim2;
    };
    
    struct PositionVsTime_size_type : public size_type{
        size_t& nx = dim1;
        size_t& nt = dim2;
    };
    
    struct coordinates {
        size_t c1,c2;
    };
    
    struct PositionVsTime_coordinates : public coordinates{
        size_t& x = c1;
        size_t& t = c2;
    };
    
    struct Field2D {
        Field2D(size_type& siz) : size_(siz), data_(size_.dim1*size_.dim2) {}
        double get(coordinates& coords) {
            return data_[coords.c1*size_.dim2 + coords.c2];
        }
        Field2D& set(coordinates& coords, double val){
            data_[coords.c1*size_.dim2 + coords.c2] = val;
            return *this;
        }
        private:
        size_type& size_;
        vector<double> data_;
    };
    
    struct PositionVersusTime : public Field2D {
        PositionVersusTime(size_type& siz) : Field2D(siz) {}
    };
    
    int main(){
       PositionVsTime_size_type siz;
       siz.nx = 5;
       siz.nt = 2;
       PositionVersusTime myField(siz);
       PositionVsTime_coordinates coords;
       coords.x = 2;
       coords.t = 0;
       myField.set(coords, 5);
       auto out = myField.get(coords);
       cout << out << endl; // will print 5
       return 0;
    }