2

I want to write a vector type of arbitrary dimension. The catch is I want to have separate fields for certain dimensions (eg: x,y,z), my solution is to use CRTP to mix in the functionality I need:

#include <unistd.h>

template <typename B, typename T, int DIM>
struct _veccore {
    // convert vector to array of underlying scalar type
    T* data(ssize_t ii) { return (static_cast<T*>(this))[ii]; }

    B operator +(const B& ov) {
        B b = reinterpret_cast<B*>(*this);
        for (ssize_t ii=0; ii < DIM; ii++) {
            b.data(ii) += ov.data(ii);
        }
        return *this;
    }   
};


template <typename T> struct _vector1d : _veccore<_vector1d<T>, T, 1> { T x;     };
template <typename T> struct _vector2d : _veccore<_vector2d<T>, T, 2> { T x,y;   };
template <typename T> struct _vector3d : _veccore<_vector3d<T>, T, 3> { T x,y,z; };

int main() {
    _vector1d<float> v1f;
    _vector2d<float> v2f;
    _vector3d<float> v3f;
}

I believe it's safe based on:

  1. If T is POD then the _vectorNd types are POD (trivally copyable and standard layout)
  2. Since it's POD, it has to be C compatible, and C requires storing fields in the order they're declared, so reordering isn't allowed.

Any other gotchas that would make this unsafe?

gct
  • 14,100
  • 15
  • 68
  • 107

1 Answers1

3

Strictly speaking, pointer arithmetic in C++ is defined based on arrays. That is, if it's not an array of objects, then you can only advance one element (to allow the treatment of individual objects as arrays of one element, you need a "past the end" pointer). You cannot treat a struct that contains two T objects as if it were a struct that contained an array of two T objects.

C++ does not allow you to pointer arithmetic from one suboject to another, unless the two subobjects are both direct members of the same array.

Now yes, in pretty much every compiler you use, this will work. But speaking with respect to the standard, it's undefined behavior, whether the type is "POD" or not.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Do you know of any compilers that won't treat this correctly? – gct Apr 08 '18 at 18:06
  • And per [this](https://stackoverflow.com/questions/7576948/does-pointer-arithmetic-have-uses-outside-of-arrays?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) question, objects have an unsigned char[] overlay, which you can do pointer arithmetic on, so I'd be hard pressed to imagine them being able to implement it where this wouldn't work. – gct Apr 08 '18 at 18:15
  • Compilers, no, but some sort of c/c++ interpreter? All bets are off. – Gem Taylor Apr 09 '18 at 11:09