Aliasing struct and array the C++ way
Use an constexpr array of pointer-to-member:
#include <math.h>struct Point { double x; double y; double z;};double dist(struct Point *p1, struct Point *p2) { constexpr double Point::* coords[3] = {&Point::x, &Point::y, &Point::z}; double d2 = 0; for (int i=0; i<3; i++) { double d = p1->*coords[i] - p2->*coords[i]; d2 += d * d; } return sqrt(d2);}
IMHO the easiest way is to just implement operator[]
. You can make a helper array like this or just create a switch...
struct Point{ double const& operator[] (std::size_t i) const { const std::array coords {&x, &y, &z}; return *coords[i]; } double& operator[] (std::size_t i) { const std::array coords {&x, &y, &z}; return *coords[i]; } double x; double y; double z;};int main() { Point p {1, 2, 3}; std::cout << p[2] - p[1]; return 0;}
struct Point { double x; double y; double z; double& operator[]( std::size_t i ) { auto self = reinterpret_cast<uintptr_t>( this ); auto v = self+i*sizeof(double); return *reinterpret_cast<double*>(v); } double const& operator[]( std::size_t i ) const { auto self = reinterpret_cast<uintptr_t>( this ); auto v = self+i*sizeof(double); return *reinterpret_cast<double const*>(v); }};
this relies on there being no packing between the double
s in your `struct. Asserting that is difficult.
A POD struct is a sequence of bytes guaranteed.
A compiler should be able to compile []
down to the same instructions (or lack thereof) as a raw array access or pointer arithmetic. There may be some problems where this optimization happens "too late" for other optimzations to occur, so double-check in performance sensitive code.
It is possible that converting to char*
or std::byte*
insted of uintptr_t
would be valid, but there is a core issue about if pointer arithmetic is permitted in this case.