Reputation: 863
I have a struct that represents a 3D position. Sometimes it's convenient to access the individual components and sometimes it's convenient to access all components as a vector (physics vector not std::vector) for which I'm using the Eigen linear algebra library. Since there are only three elements (x, y, z) and will only ever be three elements, is there anything wrong with the struct having three double&
that refer to the elements of the Eigen Matrix? i.e.:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition
{
EnuPosition(): pos(ColumnVector3::Zero()), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(double east, double north, double up): pos((ColumnVector3() << east, north, up).finished()),
east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const ColumnVector3& position): pos(position), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const EnuPosition& enu):pos(enu.pos), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition& operator=(const EnuPosition& enu)
{
this->pos = enu.pos;
return *this;
}
ColumnVector3 pos;
double& east;
double& north;
double& up;
};
It compiles fine with no warnings on g++ 5.5 with -Wall -Wextra -pedantic
in the use cases I can think of:
int main ()
{
EnuPosition enu{12.5, 34.2, 99.2};
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
ColumnVector3 x;
x << 2.0,3.0,4.0;
enu.pos = x;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::MatrixXd y;
y.resize(3,1);
y << 7.6,8.7,9.8;
enu.pos = y;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::Matrix<double,3,3> R;
enu.east = 1;
enu.north = 1;
enu.up = 1;
R << 1,2,3,4,5,6,7,8,9;
enu.pos = (R * enu.pos).eval();
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
EnuPosition enu2 = enu;
std::cout << "east: " << enu2.east
<< " north: " << enu2.north
<< " up: " << enu2.up
<< std::endl;
}
Like I said, it works, I'm just curious if it's legal and not relying on undefined behavior, etc. Or are there other issues to be cognizant of?
Upvotes: 0
Views: 60
Reputation: 18817
After you added the copy-assignment your code should be safe.
However, if you are ok with writing east()
instead of east
in your code, then a slightly more elegant solution might be this:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition : public ColumnVector3
{
EnuPosition(): ColumnVector3(ColumnVector3::Zero()) {}
EnuPosition(double east, double north, double up): ColumnVector3(east, north, up) {}
template<class X>
EnuPosition(const X& other): ColumnVector3(other) {}
double& east() {return this->x();}
double const& east() const {return this->x();}
double& north() {return this->y();}
double const& north() const {return this->y();}
double& up() {return this->z();}
double const& up() const {return this->z();}
};
If you intentionally don't want to inherit, you can of course still store the ColumnVector3
as a member.
Upvotes: 1