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) ?
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;
}